You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:15:38