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 } }
额外优化建议
- 将
Products.findOne操作加入事务,确保整个流程的原子性,避免出现数据不一致。 - 新增查询结果为空的判断,防止后续访问
dataValues时抛出空指针异常。
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

