JavaScript async/await疑问:await为何未阻塞后续代码执行?
为什么await在map回调中没有按预期阻塞后续代码执行?
你的代码里执行顺序不符合预期的核心原因是**Array.map()不会等待异步回调函数完成**,具体分析和解决方案如下:
问题本质拆解
你在notifyFollowers中使用了:
followers.map(async (follower) => { console.log("called 1st 4 times as 4 followers") const notification = await this.createNotification(follower._id, message); console.log("follower.expoPushToken") // ... 其他逻辑 });
- 每个
async (follower) => {}回调都会返回一个Promise,但map方法的特性是立刻遍历完所有元素,将每个回调的Promise收集成数组返回,不会等待这些Promise全部resolve。 - 你写的
await确实会阻塞当前回调函数内部的后续代码(也就是console.log("follower.expoPushToken")会等createNotification完成才执行),但它无法影响notifyFollowers函数里map之后的代码——所以map执行完毕后,会立刻走到console.log("is this line reached?")和this.sendPushNotification(...),此时所有map回调里的await操作还在异步执行中,pushTokens自然还没被正确填充。
两种可行解决方案
1. 使用for...of循环(逻辑直观,适合串行执行)
把map替换为for...of,逐个等待每个异步操作完成,确保pushTokens填充完毕后再执行后续代码:
async notifyFollowers(followers, message) { let pushTokens = []; const {title, body} = message; // 替换map为for...of循环 for (const follower of followers) { console.log("called 1st 4 times as 4 followers") const notification = await this.createNotification(follower._id, message); console.log("follower.expoPushToken") if (!pushTokens.includes(follower.expoPushToken)) { pushTokens.push(follower.expoPushToken); }; if (follower._id.toString() === notification.to.toString()) { // ... 你的业务逻辑 } } console.log("is this line reached?") this.sendPushNotification(pushTokens, title, body); }
2. 使用Promise.all()(并行执行,效率更高)
如果你的数据库操作允许并行执行,用Promise.all()等待所有map返回的Promise完成后,再处理后续逻辑:
async notifyFollowers(followers, message) { let pushTokens = []; const {title, body} = message; // 收集所有异步回调的Promise const promises = followers.map(async (follower) => { console.log("called 1st 4 times as 4 followers") const notification = await this.createNotification(follower._id, message); console.log("follower.expoPushToken") if (!pushTokens.includes(follower.expoPushToken)) { pushTokens.push(follower.expoPushToken); }; if (follower._id.toString() === notification.to.toString()) { // ... 你的业务逻辑 } }); // 等待所有Promise完成后再执行后续代码 await Promise.all(promises); console.log("is this line reached?") this.sendPushNotification(pushTokens, title, body); }
额外优化建议
pushTokens.includes()的时间复杂度是O(n),如果followers数量较多,建议用Set存储token,判断和添加操作的时间复杂度都是O(1):
const pushTokenSet = new Set(); // ... if (!pushTokenSet.has(follower.expoPushToken)) { pushTokenSet.add(follower.expoPushToken); }; // 最后转成数组供推送使用 const pushTokens = Array.from(pushTokenSet);
内容的提问来源于stack exchange,提问作者user6377312
相关产品推荐
相关产品推荐

