2024-04-27 23:09:12 -04:00
|
|
|
export type ProgressCallback = (progress: number) => any;
|
|
|
|
|
2024-09-22 02:38:13 -04:00
|
|
|
/**
|
|
|
|
* A promise that fires the `onProgress` callback on incremental progress
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* ```js
|
|
|
|
* const promise = new Promise((resolve, reject, progress) => {
|
|
|
|
* const max = 10;
|
|
|
|
* for(let i = 0; i < max; i++) progress(i / max);
|
|
|
|
* resolve(1);
|
|
|
|
* });
|
|
|
|
*
|
|
|
|
* console.log(promise.progress);
|
|
|
|
*
|
|
|
|
* promise.onProgress(console.log)
|
|
|
|
* .then(console.log)
|
|
|
|
* .catch(console.error)
|
|
|
|
* .finally(...);
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
*/
|
2024-04-27 23:09:12 -04:00
|
|
|
export class PromiseProgress<T> extends Promise<T> {
|
|
|
|
private listeners: ProgressCallback[] = [];
|
|
|
|
|
|
|
|
private _progress = 0;
|
|
|
|
get progress() { return this._progress; }
|
|
|
|
set progress(p: number) {
|
|
|
|
if(p == this._progress) return;
|
|
|
|
this._progress = p;
|
|
|
|
this.listeners.forEach(l => l(p));
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(executor: (resolve: (value: T) => any, reject: (reason: any) => void, progress: (progress: number) => any) => void) {
|
|
|
|
super((resolve, reject) => executor(
|
|
|
|
(value: T) => resolve(value),
|
|
|
|
(reason: any) => reject(reason),
|
2024-07-18 23:59:12 -04:00
|
|
|
(progress: number) => this.progress = progress,
|
2024-04-27 23:09:12 -04:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2024-07-18 23:59:12 -04:00
|
|
|
static from<T>(promise: Promise<T>): PromiseProgress<T> {
|
|
|
|
if(promise instanceof PromiseProgress) return promise;
|
|
|
|
return new PromiseProgress<T>((res, rej) => promise
|
|
|
|
.then((...args) => res(...args))
|
|
|
|
.catch((...args) => rej(...args)));
|
|
|
|
}
|
|
|
|
|
|
|
|
private from(promise: Promise<T>): PromiseProgress<T> {
|
|
|
|
const newPromise = PromiseProgress.from(promise);
|
|
|
|
this.onProgress(p => newPromise.progress = p);
|
|
|
|
return newPromise;
|
|
|
|
}
|
|
|
|
|
2024-04-27 23:09:12 -04:00
|
|
|
onProgress(callback: ProgressCallback) {
|
|
|
|
this.listeners.push(callback);
|
|
|
|
return this;
|
|
|
|
}
|
2024-07-18 23:59:12 -04:00
|
|
|
|
|
|
|
then(res?: (v: T) => any, rej?: (err: any) => any): PromiseProgress<any> {
|
|
|
|
const resp = super.then(res, rej);
|
|
|
|
return this.from(resp);
|
|
|
|
}
|
|
|
|
|
|
|
|
catch(rej?: (err: any) => any): PromiseProgress<any> {
|
|
|
|
return this.from(super.catch(rej));
|
|
|
|
}
|
|
|
|
|
|
|
|
finally(res?: () => any): PromiseProgress<any> {
|
|
|
|
return this.from(super.finally(res));
|
|
|
|
}
|
2024-04-27 23:09:12 -04:00
|
|
|
}
|