Skip to content

Commit

Permalink
ui/common throttlePromiseWithResult
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Jul 11, 2024
1 parent deea47a commit 4b1053a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 14 deletions.
6 changes: 3 additions & 3 deletions ui/analyse/src/study/studyCtrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ export default class StudyCtrl {
(position.path === this.ctrl.path && position.path === treePath.fromNodeList(this.ctrl.mainline))
)
this.ctrl.jump(newPath);
this.redraw();
return this.redraw();
},
deleteNode: d => {
const position = d.p,
Expand All @@ -650,7 +650,7 @@ export default class StudyCtrl {
if (!this.ctrl.tree.pathExists(d.p.path)) return this.xhrReload();
this.ctrl.tree.deleteNodeAt(position.path);
if (this.vm.mode.sticky) this.ctrl.jump(this.ctrl.path);
this.redraw();
return this.redraw();
},
promote: d => {
const position = d.p,
Expand All @@ -663,7 +663,7 @@ export default class StudyCtrl {
if (this.vm.mode.sticky) this.ctrl.jump(this.ctrl.path);
else if (this.relay) this.ctrl.jump(d.p.path);
this.ctrl.treeVersion++;
this.redraw();
return this.redraw();
},
reload: this.xhrReload,
changeChapter: d => {
Expand Down
58 changes: 47 additions & 11 deletions ui/common/src/throttle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,61 @@
* flight. Any extra calls are dropped, except the last one, which waits for
* the previous call to complete.
*/
export function throttlePromise<T extends (...args: any) => Promise<any>>(
export function throttlePromiseWithResult<R, T extends (...args: any) => Promise<R>>(
wrapped: T,
): (...args: Parameters<T>) => void {
let current: Promise<void> | undefined;
let afterCurrent: (() => void) | undefined;
): (...args: Parameters<T>) => Promise<R> {
let current: Promise<R> | undefined;
let pending:
| {
run: () => Promise<R>;
reject: () => void;
}
| undefined;

return function (this: any, ...args: Parameters<T>): void {
return function (this: any, ...args: Parameters<T>): Promise<R> {
const self = this;

const exec = () => {
afterCurrent = undefined;
const runCurrent = () => {
current = wrapped.apply(self, args).finally(() => {
current = undefined;
if (afterCurrent) afterCurrent();
if (pending) {
pending.run();
pending = undefined;
}
});
return current;
};

if (current) afterCurrent = exec;
else exec();
if (!current) return runCurrent();

pending?.reject();
const next = new Promise<R>((resolve, reject) => {
pending = {
run: () =>
runCurrent().then(
res => {
resolve(res);
return res;
},
err => {
reject(err);
throw err;
},
),
reject: () => reject(new Error('Throttled')),
};
});
return next;
};
}

/* doesn't fail the promise if it's throttled */
export function throttlePromise<T extends (...args: any) => Promise<void>>(
wrapped: T,
): (...args: Parameters<T>) => Promise<void> {
const throttler = throttlePromiseWithResult<void, T>(wrapped);
return function (this: any, ...args: Parameters<T>): Promise<void> {
return throttler.apply(this, args).catch(() => {});
};
}

Expand Down Expand Up @@ -49,7 +85,7 @@ export function finallyDelay<T extends (...args: any) => Promise<any>>(
export function throttlePromiseDelay<T extends (...args: any) => Promise<any>>(
delay: (...args: Parameters<T>) => number,
wrapped: T,
): (...args: Parameters<T>) => void {
): (...args: Parameters<T>) => Promise<void> {
return throttlePromise(finallyDelay(delay, wrapped));
}

Expand Down

0 comments on commit 4b1053a

Please sign in to comment.