我正在更新一些使用 Bluebird 承諾的舊代碼(最初不是我的)。我寧愿使用原生 ES6 Promises,但舊代碼使用了一個Promise沒有的函式,用于檢查承諾是否已解決。
這與一個類似的問題有關(是否有辦法判斷 ES6 承諾是否已履行/拒絕/解決?),但給出的解決方案非常不同,所以我想知道以下代碼是否是一種合理的方法問題。
export class QueryablePromise<T> extends Promise<T> {
private _isRejected = false;
private _isResolved = false;
private _isSettled = false;
then<TResult1 = T, TResult2 = never>(
onResolved?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
): Promise<TResult1 | TResult2> {
const newResolved = onResolved && ((value: T): TResult1 | PromiseLike<TResult1> => {
this._isResolved = true;
this._isSettled = true;
return onResolved(value);
});
const newRejected = onRejected && ((reason: any): TResult2 | PromiseLike<TResult2> => {
this._isRejected = true;
this._isSettled = true;
return onRejected(reason);
});
return super.then(newResolved, newRejected);
}
catch<TResult = never>(
onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null
): Promise<T | TResult> {
const newRejected = onRejected && ((reason: any): TResult | PromiseLike<TResult> => {
this._isRejected = true;
this._isSettled = true;
return onRejected(reason);
});
return super.catch(newRejected);
}
finally(
onFinally?: (() => void) | undefined | null
): Promise<T> {
const newFinally = onFinally && ((): void => {
this._isSettled = true;
return onFinally();
});
return super.finally(newFinally);
}
get isRejected(): boolean { return this._isRejected; }
get isResolved(): boolean { return this._isResolved; }
get isSettled(): boolean { return this._isSettled; }
}
基本上,我將傳遞給then、catch和 的每個回呼包裝finally在另一個函式中,該函式設定適當的標志,然后呼叫原始回呼。通過這種方式可以輕松地多次重復設定標志,但我認為這不是什么大問題。
我試圖想出一種方法來使用我的 Promise 子類的建構式來解決這個問題,并以某種方式在原始 executor 引數周圍放置一個包裝器來攔截resolveand 的呼叫reject,但無法完全考慮實作該型別的方法的解決方案。
我還嘗試在這個子類的建構式中簡單地添加我自己的單獨的then、catch和finally回呼,每個回呼除了設定我的狀態標志之外什么都不做,但奇怪的是導致堆疊溢位,建構式被遞回呼叫直到它爆炸.
uj5u.com熱心網友回復:
這段代碼看起來并不可靠。您需要記住 Promise 在創建時會自動決議。
使用上面的代碼,這個簡單的測驗會失敗:
const a = new QueryablePromise((res, rej) => {
setTimeout(() => { console.log('resolved'); res()}, 100)
});
setTimeout(() => {
console.log(a.isSettled)
}, 500);
會輸出
// resolved
// false
所有情況都需要考慮,不僅是在then、catch或finally被呼叫時。我可能會覆寫建構式并像這樣包裝resolve和reject函式:
class QueryablePromise<T> extends Promise<T> {
private _isRejected: boolean | undefined;
private _isResolved: boolean | undefined;
private _isSettled: boolean | undefined;
constructor (fn: (res: (value: T | PromiseLike<T>) => void, rej: (reason?: any) => void) => void) {
super((resolve, reject) => fn(
value => {
resolve(value)
this._isResolved = true;
this._isSettled = true;
},
reason => {
reject(reason)
this._isRejected = true;
this._isSettled = true;
},
));
this._isRejected = false;
this._isResolved = false;
this._isSettled = false;
}
get isRejected(): boolean { return this._isRejected!; }
get isResolved(): boolean { return this._isResolved!; }
get isSettled(): boolean { return this._isSettled!; }
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/390788.html
標籤:javascript 打字稿 承诺 es6-promise
