在Promise的.then回调中返回含Promise的对象,后续.then的val2是否已敲定?
Promise.then返回含Promise对象的行为分析
先看你给出的代码示例:
somepromise .then((step1Result) => { return { 'val1' : synchronousCalculation(), 'val2' : asyncCalculation() // << 此处 }; }) .then((result) => { // PATH2 });
核心结论
PATH2中的result['val2']不一定处于settled(敲定)状态,它大概率还是pending状态的Promise。
原因分析
Promise链的规则是:只有当你从.then回调直接返回一个Promise时,下一个.then才会等待这个Promise敲定后再执行,拿到它的最终结果。但如果返回的是包含Promise的普通对象,Promise链不会遍历对象内部去等待其中的Promise完成,而是直接把这个完整对象传递给下一个.then,此时val2就是asyncCalculation()刚返回的Promise实例,它的状态完全取决于asyncCalculation内部的异步操作进度——可能还在pending,也可能刚好完成,但你没法保证它一定是settled的。
替代解决方案(无需将方法改为async)
如果你希望在PATH2中拿到val2的最终结果,又不想改动整个方法为async,可以在第一个.then里单独等待val2的Promise完成后再返回对象:
方案一:嵌套.then处理单个异步
somepromise .then((step1Result) => { const val1 = synchronousCalculation(); // 先等待asyncCalculation完成,再组装对象返回 return asyncCalculation().then(val2 => ({ val1, val2 })); }) .then((result) => { // PATH2 这里的val2已经是异步操作的最终结果 });
方案二:用Promise.all批量处理(适合多个异步场景)
somepromise .then((step1Result) => { const val1 = synchronousCalculation(); const val2Promise = asyncCalculation(); // 同步值可以直接放入Promise.all,它会自动包装为已resolve的Promise return Promise.all([val1, val2Promise]).then(([val1, val2]) => ({ val1, val2 })); }) .then((result) => { // PATH2 这里的val2是异步操作的最终结果 });
内容的提问来源于stack exchange,提问作者Lorah Attkins
相关产品推荐
相关产品推荐

