[英]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.