如何为Promise数组的数组做 promise.all?

IT技术 javascript node.js promise
2021-02-21 04:03:20

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

[[promise1, promise2], [promise3,promise4], [promise5,promise6]],

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

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

6个回答

您还需要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获得了 other 中的分组PromisePromise.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
});
@MatíasFidemraizer 速记符号 const promise4All = Promise.all(promiseArray.map(Promise.all)) 并没有引发 Promise.all 在非对象上调用的错误。
2021-04-30 04:03:20
很高兴知道为什么我得到了反对票。好吧,所有答案都被否决了。就我而言,我已经提供了一个答案来处理 OP 解释的场景。如果以这种方式嵌套 promise 是否是一个好的设计,这不是问题。
2021-05-10 04:03:20
@Bergi 我已经修好了
2021-05-12 04:03:20
当“直接”调用时,我总是得到结果Promise.all called on non-object,但第一个代码片段有效,谢谢。
2021-05-14 04:03:20
顺便说一句,没有理由这样做Array.from(arguments),Promise只能用一个值来实现。
2021-05-17 04:03:20

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

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

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

@Bergi 非常感谢您花时间回复我在过去的几个小时里一直试图研究如何将 this 绑定到 promise,但我仍然对如何将 'this' 绑定到 'Promise' 允许 Promise.all 返回一个 promise 感到迷惑“外部” Promise.all
2021-04-24 04:03:20
同意,目前最好的解决方案。这个解决方案的美妙之处在于它保持了返回的Promise的数组深度,并且不会像其他答案一样将它们展平。解决方案本身对我来说起初有点难以理解,但一旦我理解它就变得如此明显。
2021-04-24 04:03:20
@IanH 这只是Promise.all一种方法,因此Promise如果作为回调传递需要绑定到它。一个人也可以写Promise.all(promiseArrArr.map(promiseArr => Promise.all(promiseArr)))
2021-04-30 04:03:20
@IanH 它Promise作为第二个参数map传递, 以提供this值。它与.map(Promise.all.bind(Promise))
2021-05-11 04:03:20
这无疑是最优雅的解决方案,在我看来也是最好的答案。我仍然无法理解 .map(Promise.all, Promise) 是如何工作的,但它确实如此,而且很漂亮。
2021-05-18 04:03:20

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

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),
]);
太感谢了!
2021-04-26 04:03:20

另一种选择是将您的阵列阵列展平为一个您可以Promise.all()直接使用的阵列直接从MDN 上示例中,您可以使用.reduce()and这样做.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()需要您向它传递一个数组,所以这里介绍的其他解决方案要求输入是一个严格的数组数组——该数组不能有任何简单的Promise,只有Promise数组。这种解决方案在这方面更加灵活,并且可以接受任何一种类型的输入。

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

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处理程序的值的结构(值的平面数组)不再与输入结构(Promise数组的数组)同构,因此很难匹配哪个promise 产生了哪个值。从这个意义上说,@Bergi 的方法似乎更好。
2021-05-06 04:03:20
有没有办法“忽略”返回数组中某些项目的结果?我需要清空一个数据库表,然后继续用新内容填充它,但我想将记录创建查询的结果存储在变量中。我可以一次执行所有操作Promise.all吗?
2021-05-10 04:03:20
@torazaburo - 这取决于你想对结果做什么。结果与这种方法完全一致,因此您并不是无法分辨哪个与哪个搭配,并且它们可能更容易在平面阵列中导航。这是另一种选择,取决于您想要什么。
2021-05-14 04:03:20
添加了有关此解决方案如何在Promise数组或Promise数组数组或两者的任何组合/混合上工作的信息,并以与原始Promise相同的顺序在单个展平的结果数组中提供输出。
2021-05-19 04:03:20

如果您希望展平多数组,并等待所有Promise,您现在可以执行以下操作:

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