簡體   English   中英

以干凈的方式打破javascript承諾鏈

[英]Break javascript promise chain in a clean way

我試圖鏈接承諾,以便如果一個承諾被拒絕,鏈將破裂。 我跟隨前一個SO問題的線索並嘗試將其應用於本機承諾,但我認為我誤解了事情的運作方式。

以下是我重寫代碼的方法:

Promise.resolve()
    .then(function() {
        return step(1)
            .then(null, function() {
                stepError(1);
            });
    })
    .then(function() {
        return step(2)
            .then(null, function() {
                stepError(2);
            });
    })
    .then(function() {
        return step(3)
            .then(null, function() {
                stepError(3);
            });
    });

function step(n) {
    console.log('Step '+n);
    return (n === 2) ? Promise.reject(n) : Promise.resolve(n);
}

function stepError(n) {
    console.log('Error '+n);
    return Promise.reject(n);
}

上面代碼的輸出是:

Step 1
Step 2
Error 2
Step 3
[UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): 2]

根據我的理解,第2步應該打破鏈條,不應該執行第3步。 當步驟(2)返回被拒絕的promise時,stepError(2)按預期執行。 但是因為它返回Promise.reject(2),所以下一個函數不應該被執行,並且因為最后沒有catch,所以步驟2的被拒絕的承諾似乎 - 正如預期的那樣 - 被轉發,直到它退出因為它沒有找到任何處理程序鏈。

我在這里錯過了什么?

這是一個可以玩的JSFiddle: https ://jsfiddle.net/6p4t9xyk/

根據我的理解,第2步應該打破鏈條......

,但你不小心將拒絕轉換為決議。

有關承諾的關鍵是每次調用then創建一個新的承諾,這是解決/基於什么被拒絕then回調(S)做的,並且回調處理的拒絕是拒絕轉換成分辨率除非另有故意做。

所以在這里:

return step(2)
    .then(null, function() {  // This handler converts the
        stepError(2);         // rejection into a resolution
    });                       // with the value `undefined`

這樣你就可以擁有補償錯誤的錯誤處理程序。

由於stepError返回拒絕,您可以通過添加return來繼續拒絕:

return step(2)
    .then(null, function() {
        return stepError(2);  // Added `return`
    });

...或者,完全刪除該處理程序:

return step(2);

...或者你可以throw回調,這會自動變成拒絕。

未處理的拒絕警告是由於沒有消耗stepError拒絕的事實引起的。


這是返回stepError結果的stepError

 Promise.resolve() .then(function() { return step(1) .then(null, function() { return stepError(1); // Added `return` }); }) .then(function() { return step(2) .then(null, function() { return stepError(2); // Added `return` }); }) .then(function() { return step(3) .then(null, function() { return stepError(3); // Added `return` }); }); function step(n) { console.log('Step '+n); return (n === 2) ? Promise.reject(n) : Promise.resolve(n); } function stepError(n) { console.log('Error '+n); return Promise.reject(n); } 

看起來你過分復雜了。 怎么樣:

 function step(n) { console.log('Step '+n); return (n === 2) ? Promise.reject(n) : Promise.resolve(n); } function stepError(n) { console.log('Error '+n); } Promise.resolve() .then(() => step(1)) .then(() => step(2)) .then(() => step(3)) // never here .catch(stepError); 

通常,“縮進然后”是反模式。 所有“thens”應該在同一水平上。

正如@TJCrowder所說,你忘了return錯誤處理程序的結果(或從中throw )。 為了解決這個問題,我建議你這樣做

function withStepError(n, promise) {
    return promise.catch(function(err) {
        console.log('Error '+err+' from '+n);
        throw new Error("failed at "+n);
    });
}
Promise.resolve()
.then(function() {
    return withStepError(1, step(1));
})
.then(function() {
    return withStepError(2, step(2));
})
.then(function() {
    return withStepError(3, step(3));
});

要么

function getStepError(n) {
    return function(err) {
        console.log('Error '+err+' from '+n);
        throw new Error("failed at "+n);
    };
}

Promise.resolve()
.then(function() {
    return step(1).catch(getStepError(1));
})
.then(function() {
    return step(2).catch(getStepError(2));
})
.then(function() {
    return step(3).catch(getStepError(3));
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM