我在链接.then()
来电承诺时遇到了麻烦。执行以下代码时:
var prom = new Promise(function(resolve, reject) {
//let's always fail
reject(Error("buuuu!"));
});
var thenable =
prom.then(
function(done) {
console.log("First handler: Done!: Argument: ", done);
return "First then: DONE";
},
function(fail) {
console.error("First handler: Fail!. Argument: ", fail);
return "First then: FAIL";
}
).then(
function(done) {
console.info("Second handler: Done!. Argument: ", done);
},
function(fail) {
console.error("Second handler: Fail!. Argument: ", fail);
}
);
这将在控制台中打印以下内容:
First handler: Fail!. Argument: Error {stack: (...), message: "buuuu!"}
Second handler: Done!. Argument: First then: FAIL
为什么第二个then()
调用了done
处理程序而不是fail
处理程序?
这是Chrome的错误吗? (请注意,我只对Google Chrome的行为感兴趣)
我是否需要从.then
处理程序返回预先解析/拒绝的承诺?
答案 0 :(得分:6)
为什么第二个then()调用了done处理程序而不是失败的处理程序?
因为你已经在链的第一个then()
中处理了错误,所以使用从它返回的"First then: FAIL"
字符串解析promise。
这是Chrome的错误吗?
不,这就是承诺应该如何运作。
我是否需要从.then处理程序返回预先解析/拒绝的Promise?
你可以这样做,是的。触发第二个失败处理程序的其他方法是:
只需省略第一个错误处理程序:
prom.then(function(done) {
console.log("First handler: Done!: Argument: ", done);
return "First then: DONE";
}).then(function(done) {
console.info("Second handler: Done!. Argument: ", done);
}, function(fail) {
console.error("Second handler: Fail!. Argument: ", fail);
});
或者重新抛出异常(类似于返回被拒绝的承诺):
prom.then(function(done) {
console.log("First handler: Done!: Argument: ", done);
return "First then: DONE";
}, function(fail) {
console.error("First handler: Fail!. Argument: ", fail);
throw new Error("First then: FAIL"); // or: throw fail;
// alternatively, you can return a rejected promise:
return Promise.reject(new Error("First then: FAIL"));
}).then(function(done) {
console.info("Second handler: Done!. Argument: ", done);
}, function(fail) {
console.error("Second handler: Fail!. Argument: ", fail);
});
答案 1 :(得分:6)
为什么第二个then()调用了done处理程序而不是失败的处理程序?
让我们看一下代码在同步世界中的表现:
var value;
try{
try {
throw new Error("buuu!");
console.log("First handler: Done!: Argument: ");
value = "First then: DONE";
} catch(e){
console.error("First handler: Fail!. Argument: ", e);
value = "First then: FAIL";
}
console.info("Second handler: Done!. Argument: ", value);
}catch(e){
console.error("Second handler: Fail!. Argument: ", e);
}
当您处理catch
子句中的错误时,就像处理then
子句中的错误一样,您从中恢复。承诺示例与我们的同步示例完全相同。
如果您想表示您已执行恢复逻辑,但链上仍处于拒绝状态,请重新抛出。这就是它总是在同步代码中完成的。