如何为一系列承诺数组做promise.all?

     2023-03-08     284

关键词:

【中文标题】如何为一系列承诺数组做promise.all?【英文标题】:How to do promise.all for array of array of promises? 【发布时间】:2016-07-05 19:50:19 【问题描述】:

我正在尝试并行运行函数数组,当每个人都完成时,我想要处理该结果。 我正在使用承诺。现在,我可以将所有函数放在一个数组中并且可以 Promise.all(函数数组) 但我有像

这样的数组
[[promise1, promise2], [promise3,promise4], [promise5,promise6]],

每个promise 都是promisified 函数。 Promise 参考文档说 Promise.all 中的参数应该是一个可迭代对象,我的数组是可迭代的。 但这对我不起作用。我认为它正在执行 [promise1, promise2] 作为一个承诺,而不是个人承诺。

任何人都可以帮助我如何实现它或有更好的方法吗?

【问题讨论】:

您需要Merge/flatten a multidimensional array in JavaScript?,这样您就可以根据需要拥有一组扁平的承诺。 谁对所有答案都投了反对票,请评论他们有什么问题。 promise.all 接受一个 promise 对象数组,这些对象是根据您已经调用的函数的返回值创建的。 “现在,我可以将所有函数放在一个数组中,并且可以执行 Promise.all(函数数组)”不会调用这些函数,而是会使用输入数组的重建副本来解析返回的 Promise。 【参考方案1】:

这是我的sn-p。

const a = Promise.resolve(1);
const b = Promise.resolve(2);
const c = Promise.resolve(3);
const d = Promise.resolve(4);

const e = Promise.all([a, b]);
const f = Promise.all([c, d]);

Promise.all([e, f])
    .then(res => console.log(res));

这是结果。

[[1, 2], [3, 4]]

【讨论】:

【参考方案2】:

另一种选择是将您的数组数组扁平化为一个数组,然后您可以直接使用Promise.all()。直接来自example on MDN,您可以使用.reduce().concat() 执行此操作:

var promises = [[promise1, promise2], [promise3,promise4], [promise5,promise6]];

Promise.all(promises.reduce(function(a, b)  return a.concat(b); , []))
  .then(function(results) 
    // all done here
    // results are in a flattened array
);

此解决方案允许原始的 Promise 数组包含单个 Promise 或 Promise 数组或两者的任意组合。它以这种方式很灵活,它以单个扁平结果数组的形式提供结果,这些结果与原始 promise 的顺序相同,但被扁平化为单个数组。因为Promise.all() 要求您向它传递一个数组,所以这里介绍的其他解决方案要求输入是一个严格的数组数组——该数组中不能有任何简单的承诺,只有承诺的数组。这种解决方案更灵活,可以接受任何一种输入。

例如,如果输入恰好是这样的,这将正常工作:

var promises = [promise1, promise2, [promise3, promise4], [promise5, promise6]];

查看工作演示:https://jsfiddle.net/jfriend00/dLsktyyn/


或者您可能会发现将 flatten() 函数用于其他用途很有用:

function flatten(arr) 
    return arr.reduce(function(a, b)  return a.concat(b); , []);


var promises = [[promise1, promise2], [promise3,promise4], [promise5,promise6]];

Promise.all(flatten(promises)).then(function(results) 
    // all done here
);    

编辑

或者,Javascript 数组现在有 .flat(),它将为您将数组展平一层:

const promises = [[promise1, promise2], [promise3,promise4], [promise5,promise6]];

Promise.all(promises.flat()).then(function(results) 
    // all done here
    // results are in a flattened array
);

【讨论】:

好吧,这种方法的缺点是传递给then处理程序的值的结构(一个平面数组)不再与输入结构同构(一个数组的数组)的承诺),所以很难匹配哪个承诺产生了哪个价值。从这个意义上说,@Bergi 的方法似乎更好。 @torazaburo - 这取决于你想对结果做什么。使用这种方法,结果完全符合要求,因此您不会分不清哪个与哪个相配,而且它们可能更容易在平面数组中导航。这是另一种选择,取决于你想要什么。 添加了有关此解决方案如何在一组承诺或一组承诺或两者的任何组合/混合上工作的信息,并在相同的单个扁平化结果数组中提供输出与最初的承诺一样。 有没有办法“忽略”返回数组中某些项目的结果?我需要清空一个数据库表,然后继续用新内容填充它,但我想将记录创建查询的结果存储在变量中。我可以在一个 Promise.all 中执行所有操作吗?【参考方案3】:

如果您希望展平多数组并等待所有承诺,您现在可以这样做:

const promiseAll = Promise.all(promiseArray.flat());

【讨论】:

【参考方案4】:

如果你有固定数量的子数组,我建议使用这个简单的解决方案:

const balancePromises = [...];
const symbolPromises = [...];

const [balances, symbols] = await Promise.all([
    Promise.all(balancePromises),
    Promise.all(symbolPromises)
]);

几个 promise 也可以像这样并行化:

const [
    balances,
    debt,
    name,
] = await Promise.all([
    this.contract.getBalanceOf(user),
    this.contract.getDebtOf(user),
    this.contract.getNameOf(user),
]);

【讨论】:

非常感谢!【参考方案5】:

您还需要为每个数组项调用Promise.all

const promise4all = Promise.all(
   promiseArray.map(function(innerPromiseArray) 
        return Promise.all(innerPromiseArray);
   )
);

或直接:

// Fix: Promise.all.bind is required because it seems like Promise.all
// implementation relies on "this"
const promise4All = Promise.all(promiseArray.map(Promise.all.bind(Promise)))
// or
// const promise4All = Promise.all(promiseArray.map(p => Promise.all(p)))

这样,外部Promise.all 在其他Promise.all 中获得分组承诺:

promise4all.then(function(promiseGroupResult) 
  // promiseGroupResult is the actual result of each promise group
  // and you'll be able to get each result this way: promiseGroupResult.somePropertyName
);

【讨论】:

很高兴知道我为什么投了反对票。好吧,所有答案都被否决了。就我而言,我已经提供了一个答案来处理 OP 解释的场景。如果以这种方式嵌套承诺是否是一个好的设计,那不是问题。 顺便说一句,没有理由这样做Array.from(arguments),承诺只用一个值来实现。 @Bergi 我已经修好了 当“直接”调用时,我总是得到结果Promise.all called on non-object,但是第一个代码sn-p 工作,谢谢。 @MatíasFidemraizer 简写符号 const promise4All = Promise.all(promiseArray.map(Promise.all)) 没有工作,抛出 Promise.all 在非对象上调用的错误。【参考方案6】:

您可以在所有内部数组上使用Promise.all,然后在外部数组上使用,以获得数组数组的承诺:

Promise.all(promiseArrArr.map(Promise.all, Promise)).then(arrArr => …)

请注意,Promise.all 接受一组承诺,而不是一组承诺返回函数。

【讨论】:

这无疑是最优雅的解决方案,在我看来也是最好的答案。我仍然无法理解 .map(Promise.all, Promise) 的工作原理,但它确实有效,而且很漂亮。 @IanH 将Promise 作为second argument to map 传递,以提供this 值。同.map(Promise.all.bind(Promise)) @Bergi 非常感谢您花时间回复我在过去的几个小时里一直在尝试研究如何将 this 绑定到 Promise,但我仍然对如何将 'this' 绑定到 'Promise' 感到困惑Promise.all 向“外部” Promise.all 返回一个承诺 @IanH 只是Promise.all 是一个方法,因此如果作为回调传递,则需要绑定到Promise。也可以写Promise.all(promiseArrArr.map(promiseArr => Promise.all(promiseArr))) 同意,迄今为止最好的解决方案。这个解决方案的美妙之处在于它保持了返回承诺的数组深度,并且不像其他答案那样将它们展平。解决方案本身对我来说一开始有点难以理解,但一旦我理解它就变得如此明显。【参考方案7】:

您可以使用这种方法:

var promisesArray = [
    [promise1, promise2],
    [promise3,promise4],
    [promise5,promise6]
].reduce(function (arr, item) 
    item.forEach(function (promise) 
       arr.push(promise);
    );
    return arr;
, []);
Promise.all(promisesArray).then(function () 
    // code
);

【讨论】:

面试题系列---什么是promise,解决什么问题?promise.all解决了什么问题?实现原理?回调地狱?(代码片段)

什么是Promise,我们用它来做什么?1.什么是PromisePromise是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。promise有三种状态:pen... 查看详情

Promise.all 和 Promise.race 有效地使所有承诺“得到处理”,这是一种记录在案的行为吗?

】Promise.all和Promise.race有效地使所有承诺“得到处理”,这是一种记录在案的行为吗?【英文标题】:IsitadocumentedbehaviorthatPromise.allandPromise.raceeffectivelymakeallpromises"handled"?【发布时间】:2021-01-2618:27:17【问题描述】:在下... 查看详情

什么时候然后从promise.all()的子句运行?(代码片段)

我正在盯着http://bluebirdjs.com/docs/api/promise.all.html的这段代码片段代码特别是:varfiles=[];for(vari=0;i<100;++i)files.push(fs.writeFileAsync("file-"+i+".txt","","utf-8"));Promise.all(files).then(function()console.log("allthefileswerecreated"););我的问题特别是编译器... 查看详情

使用 Promise.all() 在 Promise 实现时执行操作

】使用Promise.all()在Promise实现时执行操作【英文标题】:PerformactionsaspromisesgetfulfilledusingPromise.all()【发布时间】:2017-02-0507:54:12【问题描述】:我可以用Promise.all(array)异步解决一堆promise。然而.then()只会在所有这些承诺都得到解... 查看详情

使用 Array.map 时嵌套承诺,使用 Promise.all 但仍然无法正常工作

】使用Array.map时嵌套承诺,使用Promise.all但仍然无法正常工作【英文标题】:NestedpromiseswhileusingArray.map,usingPromise.allbutstillnotworking【发布时间】:2017-08-2804:10:29【问题描述】:我的头撞墙已经有一段时间了。我有一些节点代码可... 查看详情

并行解决承诺

】并行解决承诺【英文标题】:Parallelresolutionofpromises【发布时间】:2020-02-1706:05:27【问题描述】:如果我有一些要并行解决的承诺。我可以使用Promise.all()解决它们。但是,如果这些Promise内部也有需要解决的Promise怎么办?它们... 查看详情

如果其中一个失败,Promise.all 不会返回任何承诺 [重复]

】如果其中一个失败,Promise.all不会返回任何承诺[重复]【英文标题】:Promise.alldoesn\'treturnnoneofit\'spromisesifoneofthemfail[duplicate]【发布时间】:2018-09-0708:35:45【问题描述】:我已经发布了questionearlieraboutPromise.all和d3.jsv5,但是关于... 查看详情

使用 promises 索引映射 Promise.all 输出

】使用promises索引映射Promise.all输出【英文标题】:MapPromise.alloutputwithpromisesindex【发布时间】:2018-04-2709:16:51【问题描述】:我正在使用支持默认异步等待代码样式的nodejsv8+。在我的问题中,我试图将所有承诺推送到一个数组中... 查看详情

是否有可能在 Promise.all 中捕获所有被拒绝的承诺? [复制]

】是否有可能在Promise.all中捕获所有被拒绝的承诺?[复制]【英文标题】:IsitpossibletocatchallrejectedpromisesinPromise.all?[duplicate]【发布时间】:2017-04-1214:20:23【问题描述】:鉴于以下Promise.all(promises).then(resolved=>...).catch(rejected=>...)... 查看详情

JavaScript 中的 Promise.all:如何获得所有承诺的解析值?

】JavaScript中的Promise.all:如何获得所有承诺的解析值?【英文标题】:Promise.allinJavaScript:Howtogetresolvevalueforallpromises?【发布时间】:2017-03-3107:34:36【问题描述】:我编写了以下node.js文件:varcsv=require(\'csv-parser\');varfs=require(\'fs\')va... 查看详情

Promise.all 每次处理一组 6 个 Promise [重复]

】Promise.all每次处理一组6个Promise[重复]【英文标题】:Promise.allprocessesthepromisesinagroupof6ateachtime[duplicate]【发布时间】:2017-04-2404:01:14【问题描述】:我想同时发出一堆(比如说20个)HTTPPOST请求(以便将应用程序的信息发送到一... 查看详情

是否可以在 Promise.all 稍后向数组添加一个 Promise?

】是否可以在Promise.all稍后向数组添加一个Promise?【英文标题】:isitpossibleatPromise.alladdlateraPromisetoArray?【发布时间】:2020-02-2020:05:33【问题描述】:我在做一个项目,我问自己在Javascript中启动Promise.all是可行的,他们确实向数... 查看详情

RxJS Observables 的 Promise.all 行为?

】RxJSObservables的Promise.all行为?【英文标题】:Promise.allbehaviorwithRxJSObservables?【发布时间】:2016-06-0702:08:55【问题描述】:在Angular1.x中,我有时需要发出多个http请求并对所有响应进行处理。我会将所有的承诺放在一个数组中并... 查看详情

ES6 Promise.all() 错误句柄 - 是不是需要 .settle()? [复制]

】ES6Promise.all()错误句柄-是不是需要.settle()?[复制]【英文标题】:ES6Promise.all()errorhandle-Is.settle()needed?[duplicate]ES6Promise.all()错误句柄-是否需要.settle()?[复制]【发布时间】:2016-08-0422:53:18【问题描述】:假设我有一个处理两个承... 查看详情

数组中的 Firebase Promise 未及时解决

】数组中的FirebasePromise未及时解决【英文标题】:FirebasePromisesinarraynotresolvingintime【发布时间】:2018-07-1821:07:19【问题描述】:我正在尝试从我的firebase数据库返回3个承诺,一旦所有三个承诺都得到履行,我基本上想要呈现一个... 查看详情

节点承诺和返回值(代码片段)

...meStuff”将返回一个空数组。我也相信我明白这是因为“doPromise”没有阻塞,所以循环完成并在“doPromise”解决之前返回一个空数组。我不明白的是我如何以适当的方式完成此示例中表达的相同功能。我想我的问题是:做到这一... 查看详情

如何为python中的一系列图创建标准颜色条

】如何为python中的一系列图创建标准颜色条【英文标题】:HowcanIcreateastandardcolorbarforaseriesofplotsinpython【发布时间】:2011-12-1402:40:17【问题描述】:我使用matplotlib在python中绘制一些数据,并且这些绘图需要标准颜色条。数据由一... 查看详情

关于promise.all(代码片段)

Promise.all()方法接收单个可迭代对象(如数组)作为参数,并返回一个promise。每个Promise都用一个数值进行了决议,对Promise.all()的调用创建了新的Promisep4。这些值的存储顺序保持了待决议(resolve)的Promise顺序,与完成的先后顺序... 查看详情