Bluebird Promise.all - 多个 Promise 完成聚合成功和拒绝

Posted

技术标签:

【中文标题】Bluebird Promise.all - 多个 Promise 完成聚合成功和拒绝【英文标题】:Bluebird Promise.all - multiple promises completed aggregating success and rejections 【发布时间】:2014-11-07 04:02:54 【问题描述】:

今天有人用 bluebird 提出了一个有趣的案例,在我们不想停止给定的履行或拒绝,而是有兴趣检查最终结果的情况下,处理多个 Promise 的最佳方法是什么。一个例子:

var p1 = new Promise(function(f,r)
    setTimeout(function()
        console.log("p1");
        f("yay");
    , 100);

);

var p2 = new Promise(function(f,r)
    setTimeout(function()
        console.log("p2");
        r(new Error("boo"));
    , 200);

)

var p3 = new Promise(function(f,r)
    setTimeout(function()
        console.log("p3");
        r(new Error("yay"));
    , 300);

);

var p4 = new Promise(function(f,r)
    setTimeout(function()
        console.log("p4");
        f("yay");
    , 400);

);


//Promise.all([p1,p2, p3, p4]).then(function(p)
//    console.log("Results:",p);
//).error(function(e)
//    console.log("Error:",e);
//);

Promise.map([p1,p2, p3, p4],function(p)
    console.log("results:",p);
, concurrency:10).error(function(e)
    console.log("Error:",e);
);

在这里,如果我们运行 map 或所有被拒绝的 Promise 将导致处理程序不报告结果。

例如上面实现的运行Promise.map的结果是:

debugger listening on port 65222
p1
results: yay
p2
Error: [Error: boo]
p3
p4

Process finished with exit code 0

这里每个promise的代码都执行了,但是只报告了1个结果和1个错误。该错误导致进程停止。

如果我们取消注释 .all 我们会得到类似的行为。这次只报错。任何成功都不会到那时(可以理解)。

debugger listening on port 65313
p1
p2
Error: [Error: boo]
p3
p4

Process finished with exit code 0

考虑到这种行为,实现这样一个场景的最佳方法是什么,即所有的承诺都运行,并报告履行的承诺的结果以及任何和所有的拒绝?

类似:

Promise.aggregate([p1,p2,p3,p4]).then(function(fulfilled, rejected)
    console.log(fulfilled); //all success
    console.log(rejected); //any and all rejections/exceptions
);

【问题讨论】:

【参考方案1】:

你会使用.reflect:

Promise.all([p1,p2,p3,p4].map(x => x.reflect()).then(results => 
  results.forEach(result => 
     if(result.isFulfilled())
         // access result.value()
      else 
         // access result.reason()
     
  );
);

这曾经由 settle 函数处理,该函数传统上对数组执行此操作 - 它被 .reflect 概括,因为它将聚合与承诺检查的概念分开,并允许您执行 .settle 所做的事情,但.any.some 等其他操作。

【讨论】:

我认为 bluebird 不再支持 .settle,他们的文档中没有提及。 @silverlight513 是的,抱歉,我们不推荐使用结算 - 但它仍然可以工作。前进的方向是使用.reflect。感谢您提请我注意,我会更新答案。 @BenjaminGruenbaum .reflect 在最新版本中不适合我。具体来说,当我按原样运行文档示例时,我得到一个Uncaught TypeError: promise.reflect is not a function 错误。 Someone else 也询问了.reflect。嗯。

以上是关于Bluebird Promise.all - 多个 Promise 完成聚合成功和拒绝的主要内容,如果未能解决你的问题,请参考以下文章

多个请求执行完再执行下一个方法(vue Promise.all用法)

Promise.all和Promise.race区别,和使用场景

备忘录Promise.all包含rejected状态的多个promise完成后执行事件

Promise.all()使用方法

await 与 Promise.all 结合使用

await 与 Promise.all 结合使用