iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0
自我挑戰組

JS 加強筆記系列 第 25

Day 25:promise 實作 (3)

  • 分享至 

  • xImage
  •  

flattening

這部分是讓鏈接都可以在第一層,維持結構扁平。具體來說,在使用 promise 時,如果處理函式回傳一個值,下一個處理函式會得到該值;如果回傳 promise,則下一個處理函式會得到 resolved value,有點像中間已經經過「解開 promise 取值」的效果。例如像下方的 asyncFunc2 回傳 promise,不需要在它後面再呼叫巢狀 then,而是直接在外層呼叫就可以得到結果:

asyncFunc1()
.then(function (value1) {
    return asyncFunc2();
})
.then(function (value2) {
    // value2 是 asyncFunc2() promise 的結果
    console.log(value2);
});

也可以理解為:如果 promise P resolve 另一個 promise QP 的狀態和結果只會隨著 Q 改變,它本身不能再被 resolve。而 Q 得到結果後要同步給 P

基於以上想法,改寫實作的 resolve 方法。這是之前寫到的部分:

resolve(value) {
    if (this.promiseState !== 'pending') return;
    this.promiseState = 'fulfilled';
    this.promiseResult = value;
    this._clearAndEnqueueReactions(this.fulfillReactions);
    return this; // 讓後面可以鏈接
}

改成新增一個布林值 alreadyResolved 來鎖住外層 promise 的狀態,只要該值為真,this 就不能再 resolve,實際上狀態結果的改變在 _doResolve 這個方法內進行。而在 _doResolve 中,若回傳的值是 promise (或例子中為 thenable),當有結果時,讓外面鎖定的 promise 也有同樣結果:

resolve(value) {
    if (this.alreadyResolved) return;
    this.alreadyResolved = true;
    this._doResolve(value);
    return this;
}
_doResolve(value) {
    const self = this;
    // 判斷 'value' 是否為 thenable
    if (typeof value === 'object' && value !== null && 'then' in value) {
        // 把 'value' 的成功或失敗結果同步給 'self'
        addToTaskQueue(function () { // (A)
            value.then(
                function onFulfilled(result) {
                    self._doResolve(result);
                },
                function onRejected(error) {
                    self._doReject(error);
                });
        });
    } else {
        this.promiseState = 'fulfilled';
        this.promiseResult = value;
        this._clearAndEnqueueReactions(this.fulfillReactions);
    }
}

上一篇
Day 24:promise 實作 (2)
下一篇
Day 26:promise 實作 (4)
系列文
JS 加強筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言