我有两个代码块。首先是使用 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/