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

JavaScript异步函数中如何在map遍历完成后执行后续操作

实现方案

问题根源

原代码中setTimeout包裹的异步函数未被外部async上下文追踪,map方法仅返回了undefined数组而非可等待的Promise集合,因此无法感知所有内部异步任务的完成时机。

核心实现思路

将每个定时异步任务封装为独立Promise,通过Promise.all等待所有任务完成后再执行后续操作即可。

改造后代码

写法1:推荐写法(用delay工具函数替代setTimeout嵌套)

// 通用延迟工具函数
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function testing(summoner_name) {
  try {
    let summoner = {
      name: [summoner_name],
    };
    const id = await fetchAccountID(summoner_name);
    const matchList = await fetchMatches(id);

    // 生成所有异步任务的Promise数组
    const taskList = Object.keys(matchList.matches).map(async (key, i) => {
      // 保留原有的间隔100ms请求逻辑
      await delay(i * 100);
      const match = await fetchMatch(matchList.matches[key].gameId); 
      summoner = await getMatchStats(
        match,
        matchList.matches[key].champion,
        summoner
      );
    });

    // 等待所有异步任务全部执行完成
    await Promise.all(taskList);

    // 在这里编写你要执行的后续操作
    console.log('所有匹配数据统计完成', summoner);
  } catch (error) {
    console.log('流程执行出错:', error);
  }
}

写法2:保留原setTimeout结构的封装

async function testing(summoner_name) {
  try {
    let summoner = {
      name: [summoner_name],
    };
    const id = await fetchAccountID(summoner_name);
    const matchList = await fetchMatches(id);

    const taskList = Object.keys(matchList.matches).map((key, i) => {
      // 将每个setTimeout任务包装为Promise
      return new Promise((resolve) => {
        setTimeout(async function () {
          const match = await fetchMatch(matchList.matches[key].gameId); 
          summoner = await getMatchStats(
            match,
            matchList.matches[key].champion,
            summoner
          );
          resolve(); // 单个任务完成标记
        }, i * 100);
      })
    });

    await Promise.all(taskList);
    // 后续操作执行位置
    console.log('所有任务执行完毕');
  } catch (error) {
    console.log(error);
  }
}

补充说明

  • 如果需要容忍单条任务失败、不中断整体流程,可以将Promise.all替换为Promise.allSettled,执行完成后可遍历结果单独判断每个任务的成败状态
  • 若对getMatchStats的执行顺序有严格要求,建议改用串行遍历避免竞态问题,示例如下:
// 串行执行示例,严格保证处理顺序,间隔100ms
for (const key of Object.keys(matchList.matches)) {
  await delay(100);
  const match = await fetchMatch(matchList.matches[key].gameId);
  summoner = await getMatchStats(match, matchList.matches[key].champion, summoner);
}
// 后续操作直接写在循环后即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 12:45:03