如何使用事务循环遍历不同的Sequelize查询

问题描述 投票:0回答:2

目前,我正在尝试对需要插入的对象数组进行迭代,具体取决于数组中的项目数(来自request.body)。

预期行为:

我认为for循环会导致不同的sequelize SQL查询,这些查询将一个接一个地插入到数据库中。

--

实际行为:

实际行为是只将数组中的最后一项插入到数据库中,并且第一项被覆盖并且未插入到数据库中。

--

我的问题:

如何更改此现有逻辑,以便在使用事务/ sequelize SQL查询时能够将多个记录插入数据库?

我发送给API请求的数据是:

[{
  "venue_id": 5,
  "event_id": 13,
  "table_id": 4,
  "date_in": "2017-11-30",
  "date_out": "2017-12-31",
  "check_in": "2017-12-31T17:04:42.333Z",
  "check_out": "2017-12-31T17:05:42.333Z"
},
{
  "venue_id": 6,
  "event_id": 18,
  "table_id": 6,
  "date_in": "2017-11-30",
  "date_out": "2017-12-31",
  "check_in": "2017-12-31T17:04:42.333Z",
  "check_out": "2017-12-31T17:05:42.333Z"
}]

API调用逻辑可以在下面找到。此API请求基本上执行以下操作:

  1. 启动SQL事务以便在出现错误时提交或回滚。
  2. 搜索venueId和CustomerId以及TableId。 (如果有人试图插入一些不存在的ID)
  3. 一起计算表的价格
  4. 创建预订
  5. 提交事务并返回响应。
router.post(
  "/api/v1/reservations",
  [passport.authenticate("jwt", { session: false }), isCustomer],
  (request, response) => {

    return models.sequelize.transaction().then(t => {


      // I was trying to do this by using a for loop but it doesn't seem to work.

      for (var i = 0; i < request.body.length; i++) {

        return models.Venue.findById(request.body[i].venue_id)
          .then(venue => {
            return models.Customer.findById(request.customer.id);
          })
          .then(customer => {
            return models.Table.findAllById(request.body[i].table_id);
          })
          .then(tables => {
            var price = 0;

            for (var i = 0; i < tables.length; i++) {
              price = price + tables[i].price;
            }

            return models.Reservation.createReservation(
              request.body[i],
              price,
              request.customer.id
            ).then(reservation => {
              return reservation.addTables(tables).then(() => {
                if (request.body.length - 1 === i) {
                  t.commit().then(() => {
                    return response.status(200).send(reservation);
                  });
                }
              });
            });
          })
          .catch(error => {
            console.log(error);
            t.rollback().then(() => {
              return response.status(error.status_code).send(error.message);
            });
          });
      }
    });
  }
node.js promise sequelize.js
2个回答
1
投票

你已经使你的代码看起来如此复杂,你达到callback hell的情况,我建议使用aysnc await

在这里,我试图从你的代码中获得几乎没有错误的代码,但是你的代码仍然很复杂,如果有任何错误,请尝试解决。但这是您可以实现的预期方式:

router.post(
"/api/v1/reservations", [passport.authenticate("jwt", {
    session: false
}), isCustomer],
(request, response) => {

    return models.sequelize.transaction().then(async (t) => { // <--- ASYNC

        // I was trying to do this by using a for loop but it doesn't seem to work.

        for (var i = 0; i < request.body.length; i++) {

            try{
                let venue = await models.Venue.findById(request.body[i].venue_id) // <--- AWAIT
                let customer = await models.Customer.findById(request.customer.id); // <--- AWAIT
                let tables = await models.Table.findAllById(request.body[i].table_id); // <--- AWAIT
                let price = 0;

                for (var i = 0; i < tables.length; i++) {
                    price = price + tables[i].price;
                }

                let reservation = await models.Reservation.createReservation(
                    request.body[i],
                    price,
                    request.customer.id
                ); // <--- AWAIT   
                await reservation.addTables(tables); // <--- AWAIT
                if (request.body.length - 1 === i) {
                    await t.commit();
                    // return response.status(200).send(reservation); 
                }
            } catch (err) {
                await t.rollback();
                return response.status(error.status_code).send(error.message);
            }
        }

    });
}

希望这会帮助你得到你想要的:)


实际行为是只将数组中的最后一项插入到数据库中,并且第一项被覆盖并且未插入到数据库中。

原因:是异步行为,看看你的第一个for循环,无论你的内部代码是否执行它都将被执行,所以它将遍历所有的request.body然后你的内部代码将开始执行,这称为event loop


0
投票

我没有使用for循环,而是使用了foreach循环。经过一些小的调整似乎有效。

© www.soinside.com 2019 - 2024. All rights reserved.