我有两个代码块。首先是使用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(异步等待),另一种是使用parellel(Promise.all)。哪个有更好的表现?
答案 0 :(得分:5)
在第一个代码中,您有两个单独的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
正在等待 both 承诺完成。在第一个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 });
});
}