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

为何Promise中for循环未完成就执行resolve?如何修正?

问题原因

resolve提前执行的核心原因是**mysqlConnection.query是异步回调式API**:

  • for循环会同步遍历data里的每一条记录,快速发起所有数据库查询请求,但这些查询的回调函数(第三个参数)是在数据库操作完成后才会触发的,属于异步执行逻辑。
  • 而return resolve(...)是在for循环同步执行完毕后立刻调用的,此时所有query的回调还没开始执行,newIDs自然是空的,也就达不到预期效果。

另外你原来的代码还有几个隐藏问题:

  • 每个循环都调用beginTransaction(),同一连接下同时只能存在一个事务,这会导致事务逻辑混乱。
  • 回调函数里用了async,但mysql的回调机制不会等待这个async函数内的await PalletSkusService.createPalletSku执行完成,可能导致数据不一致。
  • 全程没有调用commit(),事务根本不会提交,数据不会真正写入数据库。
正确处理方式

改用Promise化的MySQL客户端(比如mysql2/promise,原生mysql包不支持Promise),配合async/await实现同步式的异步逻辑控制,同时正确管理事务:

// 先确保使用mysql2的Promise版本
const mysql = require('mysql2/promise');

createPallet: async (data) => {
  const newIDs = [];
  // 从连接池获取Promise式的连接
  const connection = await mysqlConnection.getConnection();

  try {
    // 开启一次全局事务
    await connection.beginTransaction();

    for (const record of data) {
      // 用await等待INSERT操作完成,获取结果
      const [results] = await connection.query(
        "INSERT INTO ...",
        [record.BatchId, record.PalletNumber, record.PrimaryWeightId]
      );
      // 等待关联的PalletSku创建完成
      await PalletSkusService.createPalletSku(...);
      // 收集插入ID
      newIDs.push(results.insertId);
    }

    // 所有操作完成后提交事务
    await connection.commit();
    return { status: true, data: newIDs };
  } catch (error) {
    // 出错时回滚事务
    await connection.rollback();
    throw error; // 抛出错误让上层处理
  } finally {
    // 无论成功失败,都释放连接回池
    connection.release();
  }
},

关键优化点

  1. Promise化异步操作:用await等待每个数据库查询和关联服务操作完成,确保for循环会按顺序等待每个迭代的异步逻辑执行完毕,再进入下一次循环。
  2. 全局事务管理:只在循环前开启一次事务,所有操作都在同一个事务内,要么全部成功提交,要么任何一步失败就回滚所有操作,保证数据一致性。
  3. 去掉冗余Promise包装:直接将createPallet定义为async函数,它会自动返回Promise,不需要手动new Promise。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:45:17