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

Node.js中Axios请求未被消费函数await的问题排查

问题分析与解决

核心问题

你的消费函数mapResolvedBankCode提前返回的原因是:内部的异步请求没有被等待。forEach循环和for循环只会触发异步操作,不会等待它们完成,循环执行完毕后立刻调用了resolve,此时Axios请求还在后台运行,返回的数组并未被异步逻辑修改。

另外,accountResolved存在不必要的Promise嵌套(Promise构造器反模式),因为Axios本身就返回Promise,无需手动包裹一层new Promise。


步骤1:简化accountResolved函数

去掉冗余的Promise包裹,直接返回Axios的Promise链:

accountResolved: (atNumber, bkCode) => {
  return axios.get(`url/foo/bar`, {
    headers: {
      'Authorization': 'token',
    }
  })
  .then(response => response.status === 200)
  .catch(error => {
    console.log(error);
    return false; // 出错时返回false,与原逻辑一致
  });
}

步骤2:修复mapResolvedBankCode的异步等待逻辑

需要收集所有异步操作的Promise,通过Promise.all等待全部完成后再返回结果。根据你的业务需求,有两种实现方式:

方式一:等待所有bankCode请求完成(保留原并发逻辑)

如果需要对每个账号尝试所有bankCode的请求,再返回结果:

mapResolvedBankCode: async (readCsvFileResponse, etransactBankCodes) => {
  const readCsvFileResponseClone = [...readCsvFileResponse];
  
  // 收集所有账号的异步处理Promise
  const allAccountPromises = readCsvFileResponseClone.map(async (item) => {
    // 收集当前账号的所有bankCode请求Promise
    const bankCheckPromises = etransactBankCodes.map(bankCode => {
      return CsvService.accountResolved(item.accountNumber, bankCode)
        .then(result => {
          if (result) {
            console.log(`resolved account ${item.accountNumber}, with bank ${bankCode}`);
            item.bankCode = bankCode;
          }
        })
        .catch(error => {
          console.error(`error in account no. ${item.accountNumber}::: `, error);
          item.bankCode = 'err';
        });
    });
    
    // 等待当前账号的所有bankCode请求完成
    await Promise.all(bankCheckPromises);
  });
  
  // 等待所有账号的处理逻辑完成
  await Promise.all(allAccountPromises);
  
  if (readCsvFileResponseClone.length > 0) {
    return readCsvFileResponseClone;
  } else {
    throw new Error('readCsvFileResponseClone not formed correctly');
  }
}

方式二:找到第一个匹配的bankCode就停止请求(优化性能)

如果只需找到第一个能匹配的bankCode,无需发起所有请求,可以改用for...of循环依次执行:

mapResolvedBankCode: async (readCsvFileResponse, etransactBankCodes) => {
  const readCsvFileResponseClone = [...readCsvFileResponse];
  
  // 遍历每个账号,依次尝试bankCode
  for (const item of readCsvFileResponseClone) {
    try {
      for (const bankCode of etransactBankCodes) {
        const result = await CsvService.accountResolved(item.accountNumber, bankCode);
        if (result) {
          console.log(`resolved account ${item.accountNumber}, with bank ${bankCode}`);
          item.bankCode = bankCode;
          break; // 找到匹配项,停止当前账号的后续请求
        }
      }
    } catch (error) {
      console.error(`error in account no. ${item.accountNumber}::: `, error);
      item.bankCode = 'err';
    }
  }
  
  if (readCsvFileResponseClone.length > 0) {
    return readCsvFileResponseClone;
  } else {
    throw new Error('readCsvFileResponseClone not formed correctly');
  }
}

关键说明

  • forEach不支持异步等待,改用map配合Promise.all或for...of循环可以正确等待异步操作完成。
  • 使用async/await语法比嵌套then/catch更易读,也更便于处理异步流程的等待逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:35:07