为何在Promise中使用setTimeout后,resolve()抛出的错误会被捕获?
Promise resolve后错误捕获的差异解释
我之前发现一个现象:Promise一旦被resolve()之后,resolve后面同步抛出的错误不会被捕获;但如果把resolve和抛错的逻辑放在setTimeout里,情况就不一样了。
示例1 - 错误未被Promise处理
var prom2 = new Promise(function(resolve, reject) { resolve("THE_RESOLVE2"); throw Error("Not caught!") sdf2; });
示例2 - 错误与Promise无关
var prom2 = new Promise(function(resolve, reject) { setTimeout(function(){ resolve("THE_RESOLVE2"); throw Error("Caught!") sdf2; }, 500); });
下面用大白话解释差异:
- 示例1的本质:Promise状态锁死,不再管后续同步错误
Promise构造函数里的代码是同步执行的,当你调用resolve()的瞬间,这个Promise的状态就被定死为「已完成(fulfilled)」了。Promise的规则是:状态一旦确定,就再也不能改变。
而构造函数里resolve之后的同步代码,虽然会继续执行,但此时Promise已经结束了它的“工作”——它只负责处理resolve/reject调用前同步抛出的错误,之后的错误它直接不管了,这些错误会变成全局层面的未捕获错误,没法被Promise的.catch()捕获。
- 示例2的本质:异步回调脱离了Promise的管辖范围
setTimeout里的函数是异步执行的,它会等当前所有同步代码都跑完,过500毫秒才会执行。这时候,Promise构造函数早就执行完了,Promise的状态还没被改变(因为resolve是在异步回调里)。
等异步回调执行时,调用resolve()会把Promise状态改成「已完成」,但之后抛出的错误,是在setTimeout的回调函数里发生的,这个回调完全不在Promise的管辖范围内——Promise管不到异步回调里的错误,所以这个错误也不会被Promise的.catch()捕获,它同样是全局未捕获错误(你觉得它“被捕获”,可能是混淆了Promise处理和全局错误处理的区别)。
简单总结:
- 同步代码里,Promise状态锁死后,后续错误它不管。
- 异步代码里,Promise管不到回调里的错误,这些错误和Promise本身无关。
内容的提问来源于stack exchange,提问作者user31782
相关产品推荐
相关产品推荐

