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

双重异步循环未等待内部循环解析Promise问题排查

问题解决:双重循环中异步操作的串行执行需求

你当前的代码使用forEach遍历异步函数,但forEach不会等待内部的异步操作完成,导致外层循环的多个周期同时执行,无法保证前一个周期的所有异步调用完成后再进入下一个周期。即使尝试了Promise.all,如果用法不对也无法解决问题。

原代码

outboundDeliveryContents.forEach(async (machine) => {
  machine.inventoryRefillPlan.forEach(async (dish) => {
    if (dish.added_quantity) {
      const { data: getOldestMealsData, error: getOldestMealsError } =
        await getOldestMeals(dish.added_quantity, dish.dish_id);

      if (getOldestMealsError)
        return { data: null, error: getOldestMealsError };

      console.log(getOldestMealsData);

      const outboundDeliveryMeals = getOldestMealsData.map((meal) => ({
        meal_id: meal.id,
        delivery_id: createOutboundDeliveryData[0].id,
        machine_id: machine.machine.machine_id,
      }));

      const {
        data: assignOutboundDeliveryItemsData,
        error: assignOutboundDeliveryItemsError,
      } = await assignOutboundDeliveryItems(outboundDeliveryMeals);

      console.log(assignOutboundDeliveryItemsData);

      if (assignOutboundDeliveryItemsError)
        return { data: null, error: assignOutboundDeliveryItemsError };
    }
  });
});

解决方案

核心问题

forEach会立即遍历所有元素,内部的async函数会被独立调用,不会阻塞后续循环迭代。要实现外层循环串行(每个machine的所有异步操作完成后再处理下一个machine),需要使用**for...of循环**,它支持异步等待。

方案1:内层串行执行(每个dish的操作按顺序完成)

如果每个dish的操作也需要按顺序执行,直接嵌套for...of:

// 外层循环用for...of,确保每个machine处理完再进下一个
for (const machine of outboundDeliveryContents) {
  // 内层循环同样用for...of,按顺序处理每个dish
  for (const dish of machine.inventoryRefillPlan) {
    if (dish.added_quantity) {
      const { data: getOldestMealsData, error: getOldestMealsError } =
        await getOldestMeals(dish.added_quantity, dish.dish_id);

      if (getOldestMealsError) {
        // 根据需求处理错误,比如抛出或返回
        throw getOldestMealsError;
      }

      console.log(getOldestMealsData);

      const outboundDeliveryMeals = getOldestMealsData.map((meal) => ({
        meal_id: meal.id,
        delivery_id: createOutboundDeliveryData[0].id,
        machine_id: machine.machine.machine_id,
      }));

      const {
        data: assignOutboundDeliveryItemsData,
        error: assignOutboundDeliveryItemsError,
      } = await assignOutboundDeliveryItems(outboundDeliveryMeals);

      console.log(assignOutboundDeliveryItemsData);

      if (assignOutboundDeliveryItemsError) {
        throw assignOutboundDeliveryItemsError;
      }
    }
  }
}

方案2:内层并行执行(同一machine下的dish操作同时进行,外层串行)

如果同一machine下的多个dish操作可以并行执行(不互相影响),可以用Promise.all包裹内层的异步操作,外层用for...of保证串行:

for (const machine of outboundDeliveryContents) {
  // 收集当前machine下所有需要执行的异步任务
  const dishTasks = machine.inventoryRefillPlan.map(async (dish) => {
    if (!dish.added_quantity) return;
    
    const { data: getOldestMealsData, error: getOldestMealsError } =
      await getOldestMeals(dish.added_quantity, dish.dish_id);

    if (getOldestMealsError) throw getOldestMealsError;

    console.log(getOldestMealsData);

    const outboundDeliveryMeals = getOldestMealsData.map((meal) => ({
      meal_id: meal.id,
      delivery_id: createOutboundDeliveryData[0].id,
      machine_id: machine.machine.machine_id,
    }));

    const {
      data: assignOutboundDeliveryItemsData,
      error: assignOutboundDeliveryItemsError,
    } = await assignOutboundDeliveryItems(outboundDeliveryMeals);

    console.log(assignOutboundDeliveryItemsData);

    if (assignOutboundDeliveryItemsError) throw assignOutboundDeliveryItemsError;
  });

  // 等待当前machine的所有dish任务完成,再进入下一个machine
  await Promise.all(dishTasks);
}

注意事项

  • 错误处理:原代码中return { data: null, error: ... }在forEach的异步函数中无效,因为这些函数的返回值不会被处理。建议用throw抛出错误,然后在外部用try/catch捕获。
  • for...of是实现异步串行循环的标准方式,它会等待每个迭代中的await完成后再进入下一次迭代。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:15:26