ES6 Promises/在多个 Promise 完成后调用一个函数(不能使用 Promises.all)[重复]
Posted
技术标签:
【中文标题】ES6 Promises/在多个 Promise 完成后调用一个函数(不能使用 Promises.all)[重复]【英文标题】:ES6 Promises/calling a function after multiple promises are fulfilled (can't use Promises.all) [duplicate] 【发布时间】:2016-08-23 17:20:55 【问题描述】:我正在编写需要这些事件按此顺序发生的 javascript:
-
同时触发多个 API 调用
在所有调用完成并返回响应后,执行一行代码
听起来很简单,但棘手的部分是我不能使用 Promises.all() 因为我仍然希望在所有承诺都已实现(无论成功与否)之后执行该行代码。除非我误解了 Promises.all(),否则一次失败会导致代码行无法在 then() 中执行,而在 error() 中执行太快。
我很可能会遗漏一些明显的东西,但我能看到的唯一其他方法是将 API 调用承诺链接在一起,但这会导致不会一次全部触发它们。所以基本上我认为我需要一个不是“快速失败”的 Promises.all() 版本。
这样做的正确方法是什么?
【问题讨论】:
Promise.all() 如果多个promise有依赖关系,则将它们一个接一个地链接起来。因此,如果一个失败,它根本不会尝试其他的,并将返回到您的 catch()。如果您对拒绝案例(错误)有容忍度,那么您应该手动将您的 Promise 与 thens 和 catchs 链接起来,并通过它们的 catch() 处理被拒绝的操作,并从该 catch() 继续执行下一个 Promise。 不确定说它不会“尝试”其他的是否准确:当它们被传递给 Promise.all 时,它们都已经开始运行了。所以无论他们有什么行为,以及任何链接到每个单独的 .then/catch() 操作都将继续运行。 【参考方案1】:要严格使用 ES6 Promise,您需要将每个 Promise 包装在另一个包装 Promise 中,当包装的 Promise 被履行或拒绝时,它会得到解决。
你可以这样做:
Promise.all(
promises.map( promise => Promise.resolve( promise ).catch( _=>_ ) )
).then ( function ( )
// All promises finished
);
这假定promises
是一组承诺和/或值。
【讨论】:
避免Promise
constructor antipattern!
@Bergi 我不认为它是一种反模式,因为它使事情更具可读性,但我对其进行了更新以避免使用 Promise 构造函数。
除了它没有,真的 :-) 顺便说一句,你可以进一步简化:.then(null, _=>_)
或 .catch(_=>_)
感谢 Bergi 和 Paulpro(以及 Dtipson),我是 Promise 的新手,仍然试图理解这里给出的答案,当我尝试我的实现时我会回复!抱歉重复的问题,我最初搜索答案时找不到该主题!
我能够使用您的答案,而且它似乎完全符合我的要求,再次感谢 Paulpro!【参考方案2】:
可能有比这更巧妙的方法,甚至是这种特定方法的更好的书面版本,但是您可以将行为链接到每个承诺(对于 then 和 catch,所以它不会使用 Promise.all)问题)更新主 Promise 中的值。
const allPromises = arrayOfPromises => Promise((resolve,reject)=>
const ln = arrayOfPromises.length,
done = 0;
const allDone => _ =>
if(++done===ln) resolve();
arrayOfPromises.map(p=>p.then(allDone).catch(allDone));
);
【讨论】:
以上是关于ES6 Promises/在多个 Promise 完成后调用一个函数(不能使用 Promises.all)[重复]的主要内容,如果未能解决你的问题,请参考以下文章
原生 ES6 承诺中 Bluebird Promise.finally 的等价物是啥? [复制]
javascript 在系列#js #promise中运行Promises
javascript 在系列#js #promise中运行Promises