javascript - Promise.all 和嵌套异步等待哪个更好?

标签 javascript node.js asynchronous promise async-await

我有两个代码块。首先是使用 async await

  async sendEmailNotifications() {
    try {
      const users = await User.find(...)

      const promises = users.map(async(user) => {
        const _promises = user.appId.map(async(app) => {
            const todayVisitorsCount = await Session.count({...})
            const yesterdayVisitorsCount = await UserSession.count({...})
            const emailObj = {
              todayVisitorsCount,
              yesterdayVisitorsCount
            }
            const sendNotification = await emailService.analyticsNotification(emailObj)
        })
        await Promise.all(_promises)
      })
      return promises
    } catch (err) {
      return err
    }
  }
(await sendEmailNotifications())

然后我使用 Promise.all

    sendEmailNotifications() {
      const users = await User.find(...)
      const promises = users.map((user) => {
        const allPromises = []
        user.appId.map((app) => {
          allPromises.push(UserSession.count({...}))
          allPromises.push(Session.count({...}))
        })
        const data = await Promise.all(allPromises)
        const emailObj = {
          todayVisitorsCount: data[0],
          yesterdayVisitorsCount: data[1]
        }
        const sendNotification = await emailService.analyticsNotification(emailObj)
      })
      return promises
  }


  sendNotification.then((data) => console.log(data))

现在我需要知道哪段代码执行得更快?一种是使用 series(async await),一种是使用 parellel(Promise.all)。哪个性能更好?

最佳答案

在第一个代码中,您有两个单独的 await 语句:

        const todayVisitorsCount = await Session.count({...})
        const yesterdayVisitorsCount = await UserSession.count({...})

而在第二个中,你只有一个,在 Promise.all 之前:

const data = await Promise.all(allPromises)

在第一个代码中,第二个Promise只有在第一个Promise完成后才会初始化,导致脚本结束前需要更长的时间。例如:

const fn = () => new Promise(resolve => setTimeout(resolve, 1000));

console.log('start');
(async () => {
  await fn();
  await fn();
  console.log('two awaits done');
})();

(async () => {
  await Promise.all([fn(), fn()]);
  console.log('Promise.all done');
})();

没有Promise.all的版本会在第一次调用fn()时暂停函数,等待fn()返回的Promise 在继续下一行之前解决(1000 毫秒)。下一行再次调用 fn()await 等待它完成(1000 多毫秒)。

相比之下,Promise.all 版本立即调用两个 fn() - 两个 Promise 都被初始化,而 await 暂停该函数正在等待两个 Promise 完成。在第一个 Promise 的初始化和第二个 Promise 的初始化之间没有停机时间。

因此,Promise.all 版本将比具有两个 await 的版本运行得更快。使用 Promise.all 会更好除非第一个 Promise (UserSession.count)必须在第二个之前完成Promise (Session.count) 开始。

通过解构并且没有不必要的变量,这就是我清理你的 Promise.all 代码的方式,你可能会认为它更具可读性:

async sendEmailNotifications() {
  const users = await User.find();
  return users.map(async (user) => {
    const [todayVisitorsCount, yesterdayVisitorsCount] = await Promise.all([
      UserSession.count(),
      Session.count()
    ]);
    await emailService.analyticsNotification({ todayVisitorsCount, yesterdayVisitorsCount });
  });
}

关于javascript - Promise.all 和嵌套异步等待哪个更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57089684/

相关文章:

javascript - 你如何在 overflow hidden 的div中居中内容

javascript - jquery position() 在 safari 和 chrome 中无法正常工作

node.js - npm start 不起作用。我已经尝试了一切。我很困惑

javascript - 在保持左结合性的同时避免左递归解析 Lambda 微积分

c# - 我应该避免使用 'async void' 事件处理程序吗?

javascript - 如何在 Android 上的 phonegap 中从本地文件创建 Blob

javascript - 如何动态创建和传递对象

javascript - req.body 中的 JSON 数据数组

JavaScript:恢复同步的异步函数

java - Flash 客户端通过全双工连接(聊天或游戏)与 Java 服务器对话的最佳方式