首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有异步和promise.all()的map()

具有异步和promise.all()的map()
EN

Stack Overflow用户
提问于 2020-04-23 05:06:17
回答 3查看 3.7K关注 0票数 4

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

我会用promise.all()

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

这里,上面写得很清楚。

Promise.all()方法返回一个单独的承诺,当作为可迭代的所有承诺都已实现时,或者当可迭代的承诺不包含承诺时,或者当可迭代包含已实现的承诺和已返回的非承诺时,该承诺就会履行。它以拒绝第一个承诺的原因拒绝,或者拒绝第一个参数捕获的错误,如果该参数使用try/catch/ that块捕获了其中的一个错误。

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

现在看下面的代码。

代码语言:javascript
运行
复制
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);

在这里,我有一个疑问。

我们正在对数组的每个元素进行迭代,并对它们进行异步操作。他们没有明确地返回任何东西。

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

为什么shuold在这里使用promise.all()

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-23 05:15:03

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

如果这是您想要的,并且您希望收集所有返回的承诺,这样您以后就可以看到它们什么时候都用Promise.all()完成了,那么这个模式运行得很好:

代码语言:javascript
运行
复制
Promise.all(someArray.map(callbackThatReturnsAPromiseHere))

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

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

.map()只是一个简单的循环。它没有任何特殊的异步特性或任何特殊的并行运行特性。如果您愿意,可以使用for循环做同样的事情。它不会让您的async回调暂停等待它被执行,因此运行它的一个副作用是您启动了一系列并行异步操作。

票数 6
EN

Stack Overflow用户

发布于 2020-04-23 05:15:08

只有当所有操作都完成时,您才需要Promise.all。例如:

代码语言:javascript
运行
复制
const promises = todayAssignedJobs.map(async todayAssigned => {
  // lots of async stuff
});

await Promise.all(promises);

// now, all Promises have resolved
// alert the user that the leaderboard is completely updated

如果一旦确定所有承诺都完成了,就不需要发生任何事情,那么Promise.all就没有意义了--您最好还是在一个循环中创建这些承诺,并将它们保持原样。在这种情况下,由于您不会使用得到的承诺数组,所以使用forEach (这是用于副作用的数组方法)更为合适。

不过,有一个问题--您不是在处理错误,而是应该处理错误,否则它们会发出警告或退出Node进程:

代码语言:javascript
运行
复制
const processJob = async (todayAssigned) => {
  const [leaderboard, created] = await Leaderboard.findOrCreate({...});

  if (!created) {
    // ...

// ...
todayAssignedJobs.forEach(async todayAssigned => {
  try {
    await processJob(todayAssigned);
  } catch(e) {
    // handle errors
  }
});
票数 3
EN

Stack Overflow用户

发布于 2020-04-23 05:15:35

在这里,Promise.all的目的是能够等待所有的承诺才能继续。

如果您在紧接console.log之前添加了一个await Promise.all(promises);,那么它将在任何承诺解决之前同步运行,而在该行之后的console.log将仅在所有承诺解析后才会出现。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61379705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档