缺少拒绝处理器时,返回的Promise状态为何仍会变化?
根据MDN文档,then()和catch()会立即返回一个pending状态的Promise,若处理器函数无返回值,返回的Promise会变为fulfilled状态且值为undefined。假设当前Promise为P0,附加在P0上的then()返回Promise P1,直接附加在P0上的catch()返回Promise P2。初始时,P1和P2均处于pending状态。若catch()的处理器运行,P2会变为fulfilled状态且值为undefined。既然then()的处理器从未运行,P1是否会一直处于pending状态?如果不是,那为何它的状态会改变,又是如何改变的?(改变状态的代码控制流程是什么?)
测试代码
const p0 = new Promise((resolve,reject) => { let num = Math.random(); setTimeout(()=> { if(num >= 0.5) { console.log("Resolved"); resolve("Promise resolved"); } else { console.log("Rejected"); reject("Promise rejected"); } }, 7000); }); const p1 = p0.then(function (resolveValue) { console.log("Then handler was executed"); console.log(resolveValue); }) console.log("P1"); console.log(p1); const p2 = p0.catch((rejectValue) => { console.log("Catch handler was executed"); console.log(rejectValue); }) console.log("P2"); console.log(p2); setTimeout(()=> { console.log("P1"); console.log(p1); }, 12000); setTimeout(()=> { console.log("P2"); console.log(p2); }, 17000);
控制台输出
P1 Promise {<pending>} [[Prototype]]: Promise [[PromiseState]]: "pending" [[PromiseResult]]: undefined P2 Promise {<pending>} [[Prototype]]: Promise [[PromiseState]]: "pending" [[PromiseResult]]: undefined Rejected Catch handler was executed Promise rejected Uncaught (in promise) Promise rejected Promise.then (async) (anonymous) @ app2.js:15 P1 Promise {<rejected>: 'Promise rejected'} [[Prototype]]: Promise [[PromiseState]]: "rejected" [[PromiseResult]]: "Promise rejected" P2 Promise {<fulfilled>: undefined} [[Prototype]]: Promise [[PromiseState]]: "fulfilled" [[PromiseResult]]: undefined
问题解答
P1不会一直处于pending状态,最终会变成rejected状态,具体原因和控制流程如下:
Promise的链式传递规则:
then()方法可以接收两个参数——onFulfilled(处理resolve状态的回调)和onRejected(处理reject状态的回调)。如果只传入onFulfilled回调(就像代码中P1的情况),当原Promise(P0)被reject时,这个then()没有对应的错误处理逻辑,它返回的Promise会直接继承原Promise的reject状态和原因。具体状态变更流程:
- 当P0调用
reject("Promise rejected")后,会遍历所有挂载在它身上的回调处理器。 - 对于P1对应的
then(),由于只提供了处理resolve的回调,无法处理P0的reject状态,因此会直接将P1标记为rejected,状态值就是P0的reject原因"Promise rejected"。 - 而P2对应的
catch()本质是then(undefined, onRejected),它的错误处理回调被执行,又因为回调没有返回值,所以P2会被标记为fulfilled,值为undefined。
- 当P0调用
控制台报错的印证:P1变成rejected状态后,没有任何后续的错误处理逻辑(代码中没有给P1添加
catch()或then()的第二个回调),因此浏览器会抛出Uncaught (in promise)的错误,这也直接证明了P1的状态确实发生了变更。
内容的提问来源于stack exchange,提问作者Intangible _pg18

