为何Promise的catch()返回已兑现Promise、then()返回已拒绝Promise?
先看你测试的第一段代码:
let with999 = Promise.resolve(999); let returnCatch = with999 .catch(reason => { console.log("catch: " + reason); }); returnCatch.then(data => { console.log("then: " + data); });
你发现原Promise with999是**已兑现(fulfilled)**状态,catch()的回调没执行,但returnCatch却跟着变成了已兑现状态,还能触发后面的then()——这其实是Promise链式调用的核心规则在起作用。
核心原理:Promise的链式方法永远返回新Promise,状态继承规则
Promise的then()、catch()本质上都是生成新Promise的方法,它们的返回值永远是一个新Promise,这个新Promise的状态遵循以下规则:
- 如果原Promise的状态匹配当前方法的回调触发条件:比如
catch()对应原Promise是rejected,then()的第一个回调对应原Promise是fulfilled——这时候会执行回调,新Promise的状态由回调的返回值决定(回调return普通值就fulfilled,return Promise就跟着那个Promise的状态走,抛出错误就rejected)。 - 如果原Promise的状态不匹配当前方法的回调触发条件:比如你例子里
catch()遇到fulfilled的原Promise,或者反向例子里then()遇到rejected的原Promise——这时候回调不会执行,新Promise会直接继承原Promise的状态和值/原因。
对应你的两个例子拆解
第一个例子:catch()遇到fulfilled的原Promise
catch(rejectedHandler)其实等价于then(undefined, rejectedHandler),当原Promise是fulfilled时,then()找不到对应的onFulfilled回调(第一个参数是undefined),所以直接把原Promise的状态和值(999)传递给新生成的returnCatch,所以returnCatch变成fulfilled,后面的then()自然会触发,输出then: 999。
第二个例子:then()遇到rejected的原Promise
你写的代码里有个小笔误,应该是returnThen.catch(...)而不是returnCatch.catch(...),修正后看逻辑:
let rejected = Promise.reject(new Error('Ups!')); let returnThen = rejected .then(reason => { console.log("then: " + reason); }); returnThen.catch(data => { console.log("catch: " + data); });
原Promise是rejected状态,then()的第一个参数是处理fulfilled的回调,不会被执行,所以returnThen直接继承原Promise的rejected状态和错误原因,后面的catch()就会触发,输出对应的错误信息。
补充:为什么不会变成pending状态?
Promise的状态一旦确定(fulfilled/rejected)就不会再变,链式方法生成的新Promise也不可能一直处于pending——要么继承原状态,要么根据回调执行结果生成新状态,不存在“回调没执行就一直pending”的情况,这是Promise规范规定的行为,目的是保证链式调用的可靠性,避免出现永远无法解决的Promise。
内容的提问来源于stack exchange,提问作者jwa

