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

Promise.all未按预期工作,回调提前返回致Batch List为空

Fix: Callback Returns Before Promise.all Completes (Batch List Empty)

咱们来拆解下你代码里导致问题的几个关键错误,然后给出修正方案:

问题根源

你的代码里有三个核心问题,导致Promise.all还没等所有异步操作完成就触发了callback,最终batchList是空的:

  1. promises数组根本没被填充
    你用了promises.concat(promise),但concat是返回新数组,不会修改原promises数组,所以这个数组一直是空的。Promise.all([])会立即resolve,这时候所有getBatchList的回调还没执行,batchList自然没内容。

  2. 回调风格函数和async/await不匹配
    this.getBatchList是基于回调的方法,你用await去等它,但它并没有返回Promise,所以await完全不起作用。而且batchList的修改是在回调里,这个回调的执行时机完全不受你的异步流程控制。

  3. 多余的嵌套async函数
    runAsyncFunctions的嵌套完全没必要,反而把异步流程搞复杂了,增加了出错的概率。


修正方案

首先,我们需要把回调风格的getBatchList封装成Promise版本(如果没法修改原方法的话),这样才能用async/await正确管理异步流程:

// 把回调式的getBatchList转成Promise版本
const getBatchListPromise = (requestId, mode) => {
  return new Promise((resolve, reject) => {
    this.getBatchList(requestId, mode, null, null, (err, result) => {
      if (err) reject(err);
      else resolve(result.items);
    });
  });
};

然后修改主函数的逻辑,正确收集并等待所有异步操作:

getByReferenceID(object, mode, limit, lastEvaluatedKey, callback) {
  let results = {};
  let requestList = [];
  let response = {};

  new Promise((resolve, reject) => {
    this.getRequestList(object, limit, lastEvaluatedKey, (err, result) => {
      console.log(result);
      results = result;
      if (err) reject(err);
      else resolve();
    });
  })
  .then(async () => {
    requestList = requestList.concat(results.items);
    
    // 正确收集所有异步操作的Promise
    const promises = requestList.map(request => {
      return getBatchListPromise(request.requestID.S, mode);
    });
    
    // 等待所有Promise完成,拿到所有批次数据
    const allBatchItems = await Promise.all(promises);
    
    // 把二维数组合并成一维,得到完整的batchList
    const batchList = allBatchItems.flat();
    
    // 构造响应再调用callback
    response = {
      "requests": requestList,
      "batches": batchList,
      "lastEvaluatedKey": results.LastEvaluatedKey
    };
    callback("", response);
  })
  .catch((error) => {
    console.log(error);
    callback(error, response);
  });
}

额外优化:全async/await改写

如果把getRequestList也封装成Promise,咱们可以把整个函数改成全async/await的写法,逻辑更清晰:

// 封装getRequestList为Promise版本
const getRequestListPromise = (object, limit, lastEvaluatedKey) => {
  return new Promise((resolve, reject) => {
    this.getRequestList(object, limit, lastEvaluatedKey, (err, result) => {
      if (err) reject(err);
      else resolve(result);
    });
  });
};

// 全async/await版本的主函数
async getByReferenceID(object, mode, limit, lastEvaluatedKey, callback) {
  let response = {};
  try {
    // 先获取请求列表
    const results = await getRequestListPromise(object, limit, lastEvaluatedKey);
    const requestList = results.items;
    
    // 收集所有批次请求的Promise
    const promises = requestList.map(request => {
      return getBatchListPromise(request.requestID.S, mode);
    });
    
    // 等待所有批次请求完成
    const allBatchItems = await Promise.all(promises);
    const batchList = allBatchItems.flat();
    
    // 构造响应并返回
    response = {
      "requests": requestList,
      "batches": batchList,
      "lastEvaluatedKey": results.LastEvaluatedKey
    };
    callback("", response);
  } catch (error) {
    console.log(error);
    callback(error, response);
  }
}

这样修改后,Promise.all会真正等待所有getBatchList操作完成,batchList就能正确填充数据,callback也会在所有异步操作完成后才被调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:15:18