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

嵌套异步函数返回Pending Promise问题:原因及解决方案

问题:异步函数返回Pending状态的Promise,如何解决?

我编写了getSettlementByUser异步函数,通过多层嵌套的async/await与Promise.all处理数据库查询逻辑,但最终输出的promiseValue仍包含处于Pending状态的Promise。明明已经用了Promise.all处理嵌套异步,却还是出现这个问题,请问原因是什么,该怎么解决?

代码示例

async getSettlementByUser(email): Promise<any> {
    let listofTerminalId = [];
    // Get current user
    let user = await this.userModel.findOne({ email: email });
    // get list of sn
    let tpeIndexes = user.bindedSn.map((item) => item);
    //list des tpes binded to current user
    let tpe = tpeIndexes.map(async (index) => {
      let list = await this.tpeModel.find({ sn: index });
      // console.log('liste des tpes', list);
      let terminalId = list.map((item) => item.terminalId);
      // console.log('terminalId', ...terminalId);
      listofTerminalId.push(...terminalId);

      console.log('listofTerminalId', listofTerminalId);
      return await listofTerminalId.map(async (item) => {
        return await this.modelSettlement
          .find({ terminalID: item })
          .then((res) => res)
          .catch((err) => console.log(err));
      });
      // console.log('settlement', settlement);
      // return settlement;
    });

    let promiseValue = await Promise.all(tpe);
    console.log('promiseValue', promiseValue);
    // // return promiseValue;
    // return tpe;
  }

输出结果

promiseValue [   [ Promise { <pending> } ],   [ Promise { <pending> }, Promise { <pending> } ],   [
    Promise { <pending> },
    Promise { <pending> },
    Promise { <pending> }   ] ]

问题原因

  1. 内层Promise未被等待:你在listofTerminalId.map(async (item) => { ... })里返回的是一个Promise数组,但没有对这个数组使用Promise.all。外层的Promise.all(tpe)只等待了tpe数组里的外层异步函数完成,但每个外层函数返回的是未被处理的内层Promise数组,所以这些内层Promise依然处于Pending状态。
  2. 全局变量导致逻辑混乱:你在循环中修改全局的listofTerminalId,多个异步操作同时向这个数组push数据,会导致每次循环都基于整个数组去查询结算数据,重复查询之前的terminalId,同时异步操作的顺序不可控,进一步加剧了Promise未完成的问题。

解决方法

重构后的代码

async getSettlementByUser(email): Promise<any> {
    // 获取当前用户
    const user = await this.userModel.findOne({ email: email });
    // 直接使用绑定的sn列表,无需额外map
    const tpeIndexes = user.bindedSn;

    // 并行处理每个sn对应的结算数据
    const settlementResults = await Promise.all(tpeIndexes.map(async (sn) => {
        // 获取当前sn关联的所有tpe记录
        const tpeList = await this.tpeModel.find({ sn });
        // 提取当前sn对应的terminalId列表
        const terminalIds = tpeList.map(item => item.terminalId);
        
        // 等待当前sn下所有terminalId的结算查询完成
        return Promise.all(terminalIds.map(async (terminalId) => {
            try {
                return await this.modelSettlement.find({ terminalID: terminalId });
            } catch (err) {
                console.error('查询结算数据失败:', err);
                return null; // 根据业务需求返回错误默认值
            }
        }));
    }));

    console.log('最终结算结果:', settlementResults);
    return settlementResults;
}

关键修改点

  • 移除全局共享变量:每个sn对应的terminalId单独处理,避免重复查询和异步操作间的数据干扰。
  • 内层Promise也用Promise.all等待:在terminalIds.map外层包裹Promise.all,确保当前sn下的所有结算查询都完成后才返回结果。
  • 简化异步逻辑:去掉不必要的then/catch,改用try/catch和await配合,代码风格更统一,错误处理更清晰。
  • 避免冗余操作:user.bindedSn.map((item) => item)是冗余操作,直接使用user.bindedSn即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:24:30