Skip to content

Commit 34c22e3

Browse files
committed
support none-overlapping queries (cancel existing)
1 parent 601d629 commit 34c22e3

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

special-pages/pages/history/app/history.service.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class HistoryService {
9191
offset: this.query.data.results.length,
9292
};
9393

94-
this.query.triggerFetch(query);
94+
this.query.nonOverlapping.triggerFetch(query);
9595
}
9696
}
9797

special-pages/pages/new-tab/app/service.js

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export class Service {
1818
DEBOUNCE_TIME_MS = 200;
1919
_broadcast = true;
2020
/** @type {undefined|((old: Data, next: Data, trigger: InvocationSource) => Data)} */
21-
accept;
21+
updater;
22+
nonOverlapping = new NonOverlapping(this);
2223
/**
2324
* @param {object} props
2425
* @param {(arg?: any) => Promise<Data>} [props.initial]
@@ -41,7 +42,7 @@ export class Service {
4142
* @param {(old: Data, next: Data, trigger: InvocationSource) => Data} fn
4243
*/
4344
withUpdater(fn) {
44-
this.accept = fn;
45+
this.updater = fn;
4546
return this;
4647
}
4748

@@ -52,7 +53,7 @@ export class Service {
5253
async fetchInitial(params) {
5354
if (!this.impl.initial) throw new Error('unreachable');
5455
const initial = await this.impl.initial(params);
55-
this._accept(initial, 'initial');
56+
this.accept(initial, 'initial');
5657
return /** @type {Data} */ (this.data);
5758
}
5859

@@ -63,7 +64,7 @@ export class Service {
6364
async triggerFetch(params) {
6465
if (!this.impl.initial) throw new Error('unreachable');
6566
const next = await this.impl.initial(params);
66-
this._accept(next, 'trigger-fetch');
67+
this.accept(next, 'trigger-fetch');
6768
return /** @type {Data} */ (this.data);
6869
}
6970

@@ -104,7 +105,7 @@ export class Service {
104105
_setupSubscription() {
105106
if (this.sub) return;
106107
this.sub = this.impl.subscribe?.((data) => {
107-
this._accept(data, 'subscription');
108+
this.accept(data, 'subscription');
108109
});
109110
}
110111

@@ -117,7 +118,7 @@ export class Service {
117118
}
118119

119120
flush() {
120-
if (this.data) this._accept(this.data, 'manual');
121+
if (this.data) this.accept(this.data, 'manual');
121122
}
122123

123124
/**
@@ -132,19 +133,18 @@ export class Service {
132133
if (this.data === null) return;
133134
const next = updaterFn(this.data);
134135
if (next) {
135-
this._accept(next, 'manual');
136+
this.accept(next, 'manual');
136137
} else {
137138
console.warn('could not update');
138139
}
139140
}
140141
/**
141142
* @param {Data} data
142143
* @param {InvocationSource} source
143-
* @private
144144
*/
145-
_accept(data, source) {
146-
if (this.accept && source !== 'initial') {
147-
this.data = /** @type {NonNullable<Data>} */ (this.accept(/** @type {NonNullable<Data>} */ (this.data), data, source));
145+
accept(data, source) {
146+
if (this.updater && source !== 'initial') {
147+
this.data = /** @type {NonNullable<Data>} */ (this.updater(/** @type {NonNullable<Data>} */ (this.data), data, source));
148148
} else {
149149
this.data = /** @type {NonNullable<Data>} */ (data);
150150
}
@@ -199,3 +199,32 @@ export class Service {
199199
this.impl.persist(this.data);
200200
}
201201
}
202+
203+
class NonOverlapping {
204+
/** @type {null|{promise: any}} */
205+
_ongoing = null;
206+
207+
/**
208+
* @param {Service} service
209+
*/
210+
constructor(service) {
211+
this.service = service;
212+
}
213+
214+
/**
215+
* @param {any} [params]
216+
*/
217+
triggerFetch(params) {
218+
if (!this.service.impl.initial) throw new Error('unreachable');
219+
if (this._ongoing?.promise) {
220+
this._ongoing.promise.cancelled = true;
221+
}
222+
// eslint-disable-next-line promise/prefer-await-to-then
223+
const promise = this.service.impl.initial(params).then((data) => {
224+
if (/** @type {any} */ (promise).cancelled) return;
225+
this.service.accept(data, 'trigger-fetch');
226+
this._ongoing = null;
227+
});
228+
this._ongoing = { promise };
229+
}
230+
}

0 commit comments

Comments
 (0)