Node.js是并行处理还是按顺序进行本机 Promise.all 处理?

2022-08-30 00:22:39

我想澄清这一点,因为文件对此不太清楚。

问1:是按顺序还是并行处理所有承诺?或者,更具体地说,它是否等同于运行链式承诺,例如Promise.all(iterable)

p1.then(p2).then(p3).then(p4).then(p5)....

还是某种其他类型的算法,其中所有,,,,等同时(并行)调用,并且一旦所有解析(或一个拒绝)就会返回结果?p1p2p3p4p5

问2:如果并行运行,是否有一种方便的方法来按顺序运行可迭代的?Promise.all

注意:我不想使用Q或Bluebird,而是所有原生的ES6规范。


答案 1

是否履行了所有承诺?Promise.all(iterable)

不,承诺不能“执行”。它们在创建任务时启动任务 - 它们仅表示结果 - 并且即使在将它们传递给之前,也在并行执行所有内容。Promise.all

Promise.all确实只等待多个承诺。它不关心它们以什么顺序解析,也不关心计算是否并行运行。

有没有一种方便的方法来按顺序运行可迭代?

如果你已经有了你的承诺,你不能做太多,但(它没有顺序的概念)。但是,如果您确实有可迭代的异步函数,则确实可以按顺序运行它们。基本上你需要从Promise.all([p1, p2, p3, …])

[fn1, fn2, fn3, …]

fn1().then(fn2).then(fn3).then(…)

要做到这一点,解决方案是使用 Array::reduce

iterable.reduce((p, fn) => p.then(fn), Promise.resolve())

答案 2

并行

await Promise.all(items.map(async (item) => { 
  await fetchItem(item) 
}))

优点:更快。即使以后失败,也将启动所有迭代。但是,它将“快速失败”。使用 Promise.allSettled 并行完成所有迭代,即使某些迭代失败。

for (const item of items) {
  await fetchItem(item)
}

优点:循环中的变量可以由每次迭代共享。其行为类似于正常的命令式同步代码。