带有 async 的 map() 与 Promise.all()

Suj*_*ari 5 javascript asynchronous node.js promise

如果我有一个元素数组并且我想对它们进行并行操作。

我会用promise.all().

我知道promise.all()接受一系列的承诺。如果我错了请纠正我,我不这么认为。

这里,说得很清楚了。

Promise.all() 方法返回单个 Promise,当作为可迭代对象传递的所有 Promise 都已实现时,或者当可迭代对象不包含 Promise 时,或者当可迭代对象包含已实现的 Promise 和已返回的非 Promise 时,该 Promise 会被实现。 。它会因为第一个被拒绝的 Promise 的原因而拒绝,或者如果第一个参数使用 try/catch/throw 块捕获了其中的错误,则使用第一个参数捕获的错误。

所以,是的,我们可以将简单的函数传递给promise.all(),如果它们返回,它就会解析,如果它们抛出错误,它就会拒绝。

现在看下面的代码。

const promises = todayAssignedJobs.map(async todayAssigned => {
  const [leaderboard, created] = await Leaderboard.findOrCreate({...});

  if (!created) {
    const rating = (todayAssigned.rating + leaderboard.rating * leaderboard.jobs_completed) / (leaderboard.jobs_completed + 1);
    const commission = todayAssigned.commission + leaderboard.commission;
    const jobsCompleted = leaderboard.jobs_completed + 1;

    await Leaderboard.update({
      rating,
      commission,
      jobs_completed: jobsCompleted,
      updated_by: 'system',
    }, {
      where: {
        id: leaderboard.id,
      },
    });
  }

  await AssignedJob.update({
    is_leaderboard_generated: true,
  }, {
    where: {
      id: todayAssigned.id,
    },
  });
});

await Promise.all(promises);
Run Code Online (Sandbox Code Playgroud)

说到这里,我有一个疑问。

我们迭代数组的每个元素并对它们进行异步操作。他们不明确返回任何内容。

所以,我认为map在这里也在做并行操作。

为什么要在promise.all()这里使用呢?

jfr*_*d00 8

.map()没有承诺意识。因此,当你async像你一样向它传递回调时,它不会关注返回的承诺。因此,它只是一个接一个地运行循环,而不等待任何返回的承诺。因此,循环中启动的所有异步操作.map()将同时进行。

如果这就是您想要的,并且您想收集所有返回的 Promise,以便稍后可以看到它们何时全部完成Promise.all(),那么此模式效果很好:

Promise.all(someArray.map(callbackThatReturnsAPromiseHere))
Run Code Online (Sandbox Code Playgroud)

而且,这是它的常见设计模式。事实上,Bluebird Promise 库有一个特殊的函数将这两个函数结合起来,称为Promise.map(). 它还提供了另一个很好的功能,让您可以控制一次可以运行多少个并发异步操作(因为它的map()操作是承诺感知的)。

听起来您正在尝试弄清楚是否应该只使用.map()而不使用Promise.all(). 如果这样做,您将并行运行异步操作,但您将不知道它们何时完成或有能力收集所有结果。您可以使用Promise.all()返回的 Promise 数组来了解它们何时全部完成和/或收集它们的解析结果。

仅供参考,.map()这只是一个简单的循环。它没有任何特殊的异步功能或任何特殊的并行运行功能。如果你愿意的话,你可以用循环做同样的事情for。它不会暂停您的async回调以等待其完成,因此运行它的副作用是您启动了一堆并行异步操作。

  • @SujeetAgrahari - 是的,`Promise.all()`的整个目的是观察一系列的承诺,并告诉你第一个承诺何时拒绝(并向你报告拒绝原因)或它们全部完成(并报告已解析值的数组)和 `.map()` 不会为您执行此操作。`.map()` 将为您收集 Promise 数组,就像它从回调收集任何返回值并运行初始循环一样,但这就是它所做的结束。 (3认同)