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

Sequelize+PostgreSQL创建优惠券:CouponProducts数据未保存问题

问题

使用Sequelize操作PostgreSQL创建优惠券接口时,请求执行成功后Coupons表已保存数据,但CouponProducts表未写入对应信息。以下是createCoupon方法代码:

async createCoupon(couponData) {
  const transaction = await models.Coupons.sequelize.transaction()

  try {
    const coupon = await models.Coupons.create(
      {
        id: uuid4(),
        couponCode: couponData.couponCode,
        discount: couponData.discount,
      },
      { transaction }
    )

    const couponId = coupon.id
    const couponProducts = Promise.all(
      couponData.productIds.map(async (product) => {
        if (product.productType === 'Department') {
          const department = await models.Products.findOne({
            where: {
              departmentId: product.departmentId,
            },
          })
          return {
            couponId: couponId,
            departmentId: product.departmentId,
            tourId: null,
            productType: product.productType,
            productName: department.dataValues.productName,
          }
        } else if (product.productType === 'Tour') {
          const tour = await models.Products.findOne({
            where: {
              tourId: product.tourId,
            },
          })
          return {
            couponId: couponId,
            departmentId: null,
            tourId: product.tourId,
            productType: product.productType,
            productName: tour.dataValues.productName,
          }
        } else {
          throw new Error(
            'Invalid product type. Use \"Department\" or \"Tour\" as product type.'
          )
        }
      })
    )
    console.log(couponProducts)
    await models.CouponProducts.bulkCreate(couponProducts, { transaction })
    await transaction.commit()
    return coupon
  } catch (error) {
    await transaction.rollback()
    throw error
  }
}

console.log(couponProducts)的输出为:

Promise { <pending> }

请求执行成功,但CouponProducts的数组数据未存入数据库,不确定bulkCreate对应的事务是否正常工作,请问哪里出错了?


分析与解决

核心问题是未等待Promise.all完成:

  • Promise.all返回的是一个处于pending状态的Promise对象,你直接将这个Promise传给bulkCreate,而非等待它解析出实际的数组数据,导致bulkCreate没有有效数据可写入。
  • 同时因为未await这个Promise,代码会直接执行transaction.commit(),此时bulkCreate的异步操作还未完成,事务提交后后续写入操作也会失效。

修正步骤

给Promise.all添加await,确保拿到解析后的数组数据:

// 原代码
const couponProducts = Promise.all(...)
// 修改为
const couponProducts = await Promise.all(...)

修正后的完整代码

async createCoupon(couponData) {
  const transaction = await models.Coupons.sequelize.transaction()

  try {
    const coupon = await models.Coupons.create(
      {
        id: uuid4(),
        couponCode: couponData.couponCode,
        discount: couponData.discount,
      },
      { transaction }
    )

    const couponId = coupon.id
    // 加上await,等待所有Promise完成,拿到实际的数组
    const couponProducts = await Promise.all(
      couponData.productIds.map(async (product) => {
        if (product.productType === 'Department') {
          const department = await models.Products.findOne({
            where: {
              departmentId: product.departmentId,
            },
            transaction // 新增:将查询纳入事务,避免数据不一致
          })
          if (!department) throw new Error('Department not found') // 新增:处理查询为空的情况
          return {
            couponId: couponId,
            departmentId: product.departmentId,
            tourId: null,
            productType: product.productType,
            productName: department.dataValues.productName,
          }
        } else if (product.productType === 'Tour') {
          const tour = await models.Products.findOne({
            where: {
              tourId: product.tourId,
            },
            transaction // 新增:将查询纳入事务,避免数据不一致
          })
          if (!tour) throw new Error('Tour not found') // 新增:处理查询为空的情况
          return {
            couponId: couponId,
            departmentId: null,
            tourId: product.tourId,
            productType: product.productType,
            productName: tour.dataValues.productName,
          }
        } else {
          throw new Error(
            'Invalid product type. Use "Department" or "Tour" as product type.'
          )
        }
      })
    )
    console.log(couponProducts) // 现在会输出实际的数组数据
    await models.CouponProducts.bulkCreate(couponProducts, { transaction })
    await transaction.commit()
    return coupon
  } catch (error) {
    await transaction.rollback()
    throw error
  }
}

额外优化建议

  1. 将Products.findOne操作加入事务,确保整个流程的原子性,避免出现数据不一致。
  2. 新增查询结果为空的判断,防止后续访问dataValues时抛出空指针异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:26:20