我无法理解以下承诺链的结果
function job(state) {
return new Promise(function(resolve, reject) {
if (state) {
resolve('success');
} else {
reject('error');
}
});
}
let promise = job(true);
promise
.then(function(data) { ///1
console.log(data);
return job(true);
})
.then(function(data) { ///2
if (data !== 'victory') {
throw 'Defeat';
}
return job(true);
})
.then(function(data) { ///3
console.log(data);
})
.catch(function(error) { ///4
console.log(error);
return job(false);
})
.then(function(data) { ///5
console.log(data);
return job(true);
})
.catch(function(error) { ///6
console.log(error);
return 'Error caught';
})
.then(function(data) { ///7
console.log(data);
return new Error('test');
})
.then(function(data) { ///8
console.log('Success:', data.message);
})
.catch(function(data) { ///9
console.log('Error:', data.message);
});
输出是
成功 打败 错误 发现错误 成功:测试
我明白为什么会打印“成功”和“失败”。 但后来我很困惑。为什么跳过3,4,5而执行6? 那么既然7抛出了错误,难道不应该执行9而不是8吗?
让我们用您在注释旁边添加的数字来调用
then
和 catch
方法返回的承诺。请注意,这些 then
和 catch
方法是同步执行的,因此我们立即有一堆 Promise,并且它们一开始都是待处理的。唯一立即满足的是 promise
(它没有得到数字,所以我们给它数字 0)。
现在让我们一步步来看:
Promise 0 (
promise
) 被分配了一个具有“成功”价值的 Promise。
回调 1 执行,因为承诺 0 已履行,所以我们得到输出“成功”。此回调返回一个新的承诺,该承诺也满足值“成功”。 Promise 1 复制了该 Promise 的状态,因此它“成功”地实现了。
回调 2 也会执行,因为承诺 1 已实现。您不会在回调编号 2 中打印任何内容,但如果您愿意,它也会被输出。
if
条件为 true,因此回调 2 会抛出错误“Defeat”。这使得 Promise 2 以“失败”为理由拒绝。
为什么跳过3,4,5
第三个回调被跳过,因为该回调仅应在 Promise 2 满足时执行。但由于它被拒绝,并且您没有为其提供 catch 回调(
then
的第二个参数不存在),promise 3 只是复制了promise 2 的状态。所以现在promise 3 也被拒绝了。
回调编号4不被跳过;它执行了!第 3 号 Promise 被拒绝,并在那里打印“Defeat”。然后,此回调继续返回一个被拒绝的 Promise (
job(false)
),其原因为“错误”(参见 job
),因此 Promise 4 也会以相同的原因拒绝。
回调 5 仅应在 Promise 4 满足时执行,但当 Promise 4 被拒绝时,它不会执行。当 Promise 4 拒绝时,这里也没有回调要执行,因此 Promise 5 只是复制 Promise 4 的状态并以“错误”为理由拒绝。
它执行了6?
回调 6 执行,因为它应该在 Promise 5 拒绝时执行——它确实这么做了——所以我们得到一个输出“错误”。此回调返回一个字符串“Error catched”,该字符串将成为 Promise 6 履行的值。
回调 7 执行,因为它应该在 Promise 6 满足时执行——它确实做到了——所以我们得到一个输出“错误捕获”。回调 7 返回一个带有消息“test”的
Error
对象。 Promise 7 以此 Error 对象作为值来实现。
那么既然7抛出了错误,是不是应该执行9而不是8呢?
这是一个误会。回调 7 not 不会抛出错误。它返回一个对象,该对象恰好是
Error
的实例,但这无关紧要。如果 then
回调返回的值不是 Promise 对象(或另一个“thenable”),那么该值将是相应 Promise 所实现的值。 Error
对象也不例外。
所以回调 8 会执行,因为它应该在 Promise 7 满足时执行——它确实做到了——所以我们得到一个输出“错误捕获”。这里没有返回任何内容,这意味着 Promise 8 满足了值
undefined
。
回调 9 不执行,因为它应该在 Promise 8 拒绝时执行,但它实现了。由于 Promise 8 履行时没有处理程序,因此 Promise 9 仅复制 Promise 8 的状态。由于 Promise 9 没有附加回调,因此不会执行任何其他操作。
我希望这能澄清这一点。
虽然 trincot 的解释非常详细,但帮助我理解承诺链的是将其可视化。
这是您的代码示例中发生的情况:
值得一提的是:
unhandled promise exception
,导致nodejs进程崩溃