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

异步函数未等待代码执行完成,广播空数组问题求助

问题:异步任务未完成就执行广播,导致首次广播空数组

我正在编写一个从API拉取消息并筛选含图片消息的脚本,该API有多个端点对应不同消息批次,需要收集所有符合条件的消息(示例中有3个链接,会打印3次"test")。

当前问题是messageGetter()函数尚未完全执行完毕,broadcast()就被调用了,导致首次执行脚本时广播空数组,第二次执行才能获取到所需内容。

现有代码

module.exports = {
  async execute(app) {
    await fetchImages(app);
    await interaction.reply("Getting Images");
  },
};

async function fetchImages(app) {
  app.link.forEach(async (link) => {
    if (link.type === 0) {
      await messageGetter(link);
    }
  });
  console.log("here");
  broadcast({ type: "imageLinks", data: imageLinks });
  imageLinks.splice(0, imageLinks.length);
}

async function messageGetter(link, limit = 500) {
  const sum_messages = [];
  let last_id;

  while (true) {
    const options = { limit: 100 };
    if (last_id) {
      options.before = last_id;
    }

    const messages = await link.messages.fetch(options);
    sum_messages.push(...messages.values());
    last_id = messages.last().id;

    if (messages.size != 100 || sum_messages >= limit) {
      break;
    }
  }

  sum_messages.forEach((message) => {
    if (message.attachments.size > 0) {
      message.attachments.forEach((attachment) => {
        if (attachment.url.match(/\.(jpeg|jpg|gif|png)$/i)) {
          imageLinks.push(attachment.url);
        }
      });
    }
  });
console.log("test");
}

日志输出

here
test
test
test

修复方案

问题根源

forEach循环不支持异步等待,循环内的async回调会被立即触发,但fetchImages函数不会等待所有回调中的await messageGetter(link)执行完成,就直接向下执行broadcast,导致此时imageLinks还未收集到数据。

修复步骤

将forEach替换为Promise.all,让fetchImages等待所有messageGetter异步任务完成后再执行广播:

修改后的fetchImages函数

async function fetchImages(app) {
  // 过滤符合条件的链接,生成异步任务数组
  const tasks = app.link
    .filter(link => link.type === 0)
    .map(link => messageGetter(link));
  
  // 等待所有异步任务全部完成
  await Promise.all(tasks);
  
  console.log("here");
  broadcast({ type: "imageLinks", data: imageLinks });
  imageLinks.splice(0, imageLinks.length);
}

额外优化(可选)

原代码中imageLinks是全局变量,容易引发多次执行时的状态污染,建议改为局部变量,并通过参数传递给messageGetter,同时修正sum_messages >= limit的错误判断(数组需用length属性比较):

优化后完整代码

module.exports = {
  async execute(app) {
    await fetchImages(app);
    await interaction.reply("Getting Images");
  },
};

async function fetchImages(app) {
  // 局部变量存储图片链接,避免全局状态污染
  const imageLinks = [];
  
  const tasks = app.link
    .filter(link => link.type === 0)
    .map(link => messageGetter(link, imageLinks));
  
  await Promise.all(tasks);
  
  console.log("here");
  broadcast({ type: "imageLinks", data: imageLinks });
}

async function messageGetter(link, imageLinks, limit = 500) {
  const sum_messages = [];
  let last_id;

  while (true) {
    const options = { limit: 100 };
    if (last_id) {
      options.before = last_id;
    }

    const messages = await link.messages.fetch(options);
    sum_messages.push(...messages.values());
    last_id = messages.last().id;

    // 修正数组长度判断逻辑
    if (messages.size != 100 || sum_messages.length >= limit) {
      break;
    }
  }

  sum_messages.forEach((message) => {
    if (message.attachments.size > 0) {
      message.attachments.forEach((attachment) => {
        if (attachment.url.match(/\.(jpeg|jpg|gif|png)$/i)) {
          imageLinks.push(attachment.url);
        }
      });
    }
  });
  console.log("test");
}

内容的提问来源于stack exchange,提问作者Pazulay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:15:28