目前,我正在尝试对需要插入的对象数组进行迭代,具体取决于数组中项的数量(来自request.body)。
预期的行为:
我认为for循环将导致不同的顺序SQL查询,这些查询将一个接一个地插入数据库。
-
实际行为:
实际的行为是,只有数组中的最后一项插入数据库,而第一个被覆盖且没有插入数据库。
-
我的问题:
如何更改现有逻辑,以便在使用事务/顺序化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请求基本上执行以下操作:
- 启动SQL事务以便在出现问题时进行提交或回滚。
- 搜索场所ID,客户ID和TableId。 (以防有人尝试插入一些不存在的ID)
- 一起计算表的价格
- 创建预订
- 提交事务并返回响应。
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);
});
});
}
});
}
答案 0 :(得分: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
答案 1 :(得分:0)
我使用了foreach循环,而不是使用for循环。经过一些小的调整后,它似乎可以正常工作。