如何使用 sequelize 事务删除多个不同的数据以及 express.js 中的某些条件?

How to use a sequelize transaction to delete multiple different data along with some conditions in express.js?

我正在为在线汽车销售制作 API。我需要使用 sequelize 事务同时删除一些关于汽车销售的数据。有2个条件。首先,如果汽车已售出,那么我需要更新汽车状态,但同时创建购买和反馈数据。如果某辆车已经在其他地方出售,那么我需要删除这辆车,以及该车的浏览量、点赞数和议价数据,并创建有关该车销售情况的反馈。

例如,如果需要删除的汽车的第 3 条数据违反约束(导致错误),则删除该汽车的第 1 条和第 2 条数据将与任何删除的 /创建数据。

我尝试过使用 sequelize 事务,但即使有任何数据尚未删除它也会提交(导致错误)

这是已经制作好的代码。

async function deleteCarAsAdmin(req, res) {
  let error = [];
  try {
    // id, reasonType, comment, price, paymentMethod, buyerUserType, sellDate
    const { deleteData } = req.body;
    const trans = await sequelize.transaction();
    const lengtData = deleteData.length;
    function customForEach(callback) {
      const array = this;
      let index = 0;
      const next = () => {
        index++;
        if (array.length > 0) {
          callback(array.shift(), index, next);
        }
      };
      next();
    }
    Array.prototype.customForEachFunc = customForEach;
    const promise = await new Promise((resolve, reject) => {
      const resRej = (errlength, lengtData, deleteDatalength) => {
        if (errlength == lengtData) {
          return reject({ message: error });
        }
        if (deleteDatalength == 0) {
          return resolve();
        }
      };
      deleteData.customForEachFunc(async (data, index, next) => {
        const carData = await models.Car.findByPk(data.id, { transaction: trans });
        if (!carData) {
          apiResponse._redconsole(`GA KETEMU BANG / Car Id ${data.id} Not Found`);
          error.push(`carID : ${data.id} Not Found`);
          console.log(`index : ${index}`);
          console.log(`length ${deleteData.length}`);
          console.log(error);
          resRej(error.length, lengtData, deleteData);
          return next();
        }
        if (validator.isInt(data.id ? data.id.toString() : '') === false) {
          apiResponse._redconsole(`Car Id ${data.id} MustBe Integer`);
          error.error.push('Id Must Be an Integer,\n');
          resRej(error.length, lengtData, deleteData);
          return next();
        }
        if (!data.reasonType) {
          apiResponse._redconsole(`Please Provide Your Reason For Deleting carId ${data.id}!`);
          error.push(`carID : ${data.id} Please Provide Your Reason For Deleting carId ${data.id}`);
          resRej(error.length, lengtData, deleteData);
          return next();
        }
        let regex = /^(?!\s*$).+/;
        if (!data.comment || !regex.test(data.comment)) {
          apiResponse._redconsole(`Please Provide Your Comment For Deleting carId ${data.id}!`);
          error.push(`Please Provide Your Coment For Deleting carId ${data.id}`);
          resRej(error.length, lengtData, deleteData);
          return next();
        }
        let reasonId = null;
        const getReasonType = await models.ReasonType.findOne(
          {
            where: { typeReason: data.reasonType },
            attributes: ['id']
          },
          { transaction: trans }
        ).catch(async err => {
          apiResponse._redconsole(err.message`1`);
          error.push(`${err.message}\n`);
          resRej(error.length, lengtData, deleteData);
          return next();
        });
        if (getReasonType) {
          reasonId = getReasonType.id;
        }
        const now = moment(data.sellDate)
          .tz('Asia/Jakarta')
          .format('YYYY-MM-DD HH:mm:ss');
        if (data.reasonType === 1) {
          if (!data.price) {
            apiResponse._redconsole(`Please Provide Your Price For CarId ${data.id}`);
            error.push(`Please Provide Your Price For carId ${data.id},\n`);
            resRej(error.length, lengtData, deleteData);
            return next();
          }
          if (!data.paymentMethod) {
            apiResponse._redconsole(`Please Provide Your Payment Method For CarId ${data.id}`);
            error.push(`Please Provide Your Payment Method For carId ${data.id},\n`);
            resRej(error.length, lengtData, deleteData);
            return next();
          }
          if (!data.sellDate) {
            apiResponse._redconsole(`Please Provide Your Payment Date For CarId ${data.id}`);
            error.push(`Please Provide Your Payment Date For carId ${data.id},\n`);
            resRej(error.length, lengtData, deleteData);
            return next();
          }
          if (!data.buyerUserType) {
            apiResponse._redconsole(`Please Provide Your Type Of Customer For CarId ${data.id}`);
            error.push(`Please Provide Your Type Of Customer For carId ${data.id},\n`);
            resRej(error.length, lengtData, deleteData);
            return next();
          }
          await models.Purchase.create(
            {
              userId: carData.userId,
              carId: data.id,
              price: data.price,
              paymentMethod: data.paymentMethod
            },
            { transaction: trans }
          ).then(async datas => {
            //update car status
            await datas
              .update(
                {
                  status: 2
                },
                {
                  where: { id: datas.carId }
                },
                { transaction: trans }
              )
              .catch(async err => {
                apiResponse._redconsole(`${err.message} carId ${data.id}`);
                error.push(` ${err.message},\n`);
                await trans.rollback();
                resRej(error.length, lengtData, deleteData);
                return next();
              });

            //create feedback

            await models.FeedBack.create(
              {
                carId: data.id,
                userId: carData.userId,
                reasonType: reasonId,
                comment: data.comment,
                paymentMethod: data.paymentMethod == 0 ? 'kredit' : 'tunai',
                buyerUserType: data.buyerUserType,
                sellDate: now
              },
              { transaction: trans }
            ).catch(async err => {
              apiResponse._redconsole(`${err.message} carId ${data.id}`);
              error.push(` ${err.message},\n`);
              await trans.rollback();
              resRej(error.length, lengtData, deleteData);
              return next();
            });
            await models.Car.destroy(
              {
                where: { id: data.id }
              },
              { transaction: trans }
            ).catch(async err => {
              apiResponse._redconsole(`${err.message} carId ${data.id}`);
              error.push(` ${err.message},\n`);
              await trans.rollback();
              resRej(error.length, lengtData, deleteData);
              return next();
            });
          });
        } else if (data.reasonType == 2) {
          //create feedback
          await models.FeedBack.create(
            {
              carId: data.id,
              userId: carData.userId,
              reasonType: reasonId,
              comment: data.comment
            },
            { transaction: trans }
          ).catch(async err => {
            apiResponse._redconsole(`${err.message} carId ${data.id}`);
            error.push(` ${err.message},\n`);
            resRej(error.length, lengtData, deleteData);
            await trans.rollback();
            return next();
          });

          //delete car
          await models.Car.destroy(
            {
              where: { id: data.id }
            },
            { transaction: trans }
          ).catch(async err => {
            apiResponse._redconsole(`${err.message} carId ${data.id}`);
            error.push(` ${err.message},\n`);
            resRej(error.length, lengtData, deleteData);
            await trans.rollback();
            return next();
          });

          //delete bargain
          const bargainData = await models.Bargain.findOne({
            where: {
              carId: data.id
            }
          });
          if (bargainData) {
            await models.Bargain.destroy(
              {
                where: { carId: data.id }
              },
              { transaction: trans }
            ).catch(async err => {
              apiResponse._redconsole(`${err.message} carId ${data.id}`);
              error.push(` ${err.message},\n`);
              await trans.rollback();
              resRej(error.length, lengtData, deleteData);
              return next();
            });
          }

          //delete like
          console.log('delete like');
          const likeData = await models.Like.findOne({
            where: {
              carId: data.id
            }
          });
          if (likeData) {
            await models.Like.destroy(
              {
                where: { carId: data.id }
              },
              { transaction: trans }
            ).catch(async err => {
              apiResponse._redconsole(`${err.message} carId ${data.id}`);
              error.push(` ${err.message},\n`);
              await trans.rollback();
              resRej(error.length, lengtData, deleteData);
              return next();
            });
          }

          //delele view
          console.log('delete view');
          console.log(data.id);
          const viewData = await models.View.findOne({
            where: {
              carId: data.id
            }
          });
          console.log(viewData);
          if (viewData) {
            await models.View.destroy(
              {
                where: { carId: data.id }
              },
              { transaction: trans }
            ).catch(async err => {
              apiResponse._redconsole(`${err.message} carId ${data.id}`);
              error.push(` ${err.message},\n`);
              await trans.rollback();
              resRej(error.length, lengtData, deleteData);
              return next();
            });
          }
        }
        resRej(error.length, lengtData, deleteData);
        return next();
      });
    });
    await trans.commit();
    return res.status(200).json({
      success: true
    });
  } catch (err3) {
    return res.status(500).json({
      success: false,
      errors: err3.message
    });
  }
}

请帮忙。谢谢,抱歉英文不好

至少我注意到你混淆了 awaitthen/catch。仅使用 await 并在需要时将其包装到 try/catch 中。
同样在 await datas.update 中,您应该在第二个参数中指定 transaction 而不是在第三个参数中:

await datas
              .update(
                {
                  status: 2
                },
                {
                  where: { id: datas.carId },
                  transaction: trans
                }
              )

destroy也是如此:

await models.Car.destroy(
              {
                where: { id: data.id },
                transaction: trans
              }
            )
...
await models.Bargain.destroy(
              {
                where: { carId: data.id },
                transaction: trans
              }
            )
...
await models.Like.destroy(
              {
                where: { carId: data.id },
                transaction: trans
              }
            )
...
await models.View.destroy(
              {
                where: { carId: data.id },
                transaction: trans
              }
            )

并且您忘记在 findOne 中指明交易:

const bargainData = await models.Bargain.findOne({
            where: {
              carId: data.id
            },
            transaction: trans
          })
...
const likeData = await models.Like.findOne({
            where: {
              carId: data.id
            },
            transaction: trans
          })
...
const viewData = await models.View.findOne({
            where: {
              carId: data.id
            },
            transaction: trans
          });