sequelize递减的更好解决方案
better solution for sequelize decrement
我是续集的新手并尝试做递减。我有两个型号的产品和订单,在产品中有 productStock 列,在订单中有数量列。我想做的是,当我创建新订单时,productStock 将根据订购数量减少。代码如下:
router.post('/', async (req, res) => {
try {
const { productId, quantity } = req.body
const postData = new Order({
productId,
quantity
})
const resultdata = await Product.findOne({ where: {productId: postData.productId} }).then( product => {
if(product.productStock <= 0) {
return res.json({
status: "failed",
message: "out of stock"
})
} else {
product.decrement('productStock', {by: postData.quantity})
return postData.save()
}
} ).catch(err => err)
res.send({
status: "success",
data: resultdata
})
} catch (err) {
throw err
}
})
我得到了我想要的结果,但问题是当 productStock <= 0 结果是正确的,但我在终端中收到如下错误:
(node:13236) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Socket'
| property '_writableState' -> object with constructor 'WritableState'
| property 'afterWriteTickInfo' -> object with constructor 'Object'
--- property 'stream' closes the circle
at JSON.stringify (<anonymous>)
at stringify (D:\Projects\sequelize-association\node_modules\express\lib\response.js:1123:12)
at ServerResponse.json (D:\Projects\sequelize-association\node_modules\express\lib\response.js:260:14)
at ServerResponse.send (D:\Projects\sequelize-association\node_modules\express\lib\response.js:158:21)
at D:\Projects\sequelize-association\routes\orders.js:30:13
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:13236) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated
either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:13236) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
请任何人帮忙,而且我认为我的代码由于在 try/catch 中使用了承诺 then/catch 而不干净,所以如果有更好的解决方案适合我的情况,那将是非常感谢... .
我认为错误是在 resultData
被 return 编辑到 res.send(...)
时发生的。它可能在某处有一个循环引用。为了避免这种情况,一种选择是 return 类似 JSON.stringify(resultData)
的东西,这样可以防止错误,尽管我不确定它会有多大用处....
有几点需要注意:
- 针对数据库创建新对象的建议方法是使用
.create()
方法或 .build()
方法后跟 .save()
,至少在 [=17 的版本 6 中是这样=] (creating new instances)。我实际上不确定如果值只是传递给构造函数会发生什么,如 new Order({ productId, quantity })
,但更新数据库必须是异步的,并且对象实例化并不意味着在 javascript 中是异步的].
.catch(err => err)
可能不会按照您想要的方式处理错误。
- 当
product.productStock <= 0
时,res.json(...)
的值被return编辑并存储在resultData
中。随后,resultData
在 res.send(...)
中被 return 编辑,这在 express.js
中是不允许的。也就是说,同一个http请求不能有两个response。
- 当需要对数据库执行一系列需要原子化的步骤时,sequelize 提供 transactions,这很有帮助。
考虑到这一点,我会尝试重构为类似下面的代码。可能还有其他方法可以改进,但至少错误应该消失,上面的一些问题将得到修复。
const sequelize = new Sequelize(/* connection string or other db options here */)
router.post('/', async (req, res) => {
const { productId, quantity } = req.body
let t = await sequelize.transaction()
try {
let order,
product
product = await Product.findOne({
where: { productId },
transaction: t
})
if (!product || product.productStock <= 0) {
await t.rollback()
res.json({
status: "failed",
message: "out of stock"
})
} else {
order = await Order.create({
productId,
quantity
}, {
transaction: t
})
await product.decrement('productStock', {
by: order.quantity,
transaction: t
})
await t.commit()
res.send({
status: "success",
data: JSON.stringify(order)
})
}
} catch (err) {
if (t) {
await t.rollback()
}
}
})
我是续集的新手并尝试做递减。我有两个型号的产品和订单,在产品中有 productStock 列,在订单中有数量列。我想做的是,当我创建新订单时,productStock 将根据订购数量减少。代码如下:
router.post('/', async (req, res) => {
try {
const { productId, quantity } = req.body
const postData = new Order({
productId,
quantity
})
const resultdata = await Product.findOne({ where: {productId: postData.productId} }).then( product => {
if(product.productStock <= 0) {
return res.json({
status: "failed",
message: "out of stock"
})
} else {
product.decrement('productStock', {by: postData.quantity})
return postData.save()
}
} ).catch(err => err)
res.send({
status: "success",
data: resultdata
})
} catch (err) {
throw err
}
})
我得到了我想要的结果,但问题是当 productStock <= 0 结果是正确的,但我在终端中收到如下错误:
(node:13236) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Socket'
| property '_writableState' -> object with constructor 'WritableState'
| property 'afterWriteTickInfo' -> object with constructor 'Object'
--- property 'stream' closes the circle
at JSON.stringify (<anonymous>)
at stringify (D:\Projects\sequelize-association\node_modules\express\lib\response.js:1123:12)
at ServerResponse.json (D:\Projects\sequelize-association\node_modules\express\lib\response.js:260:14)
at ServerResponse.send (D:\Projects\sequelize-association\node_modules\express\lib\response.js:158:21)
at D:\Projects\sequelize-association\routes\orders.js:30:13
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:13236) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated
either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:13236) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
请任何人帮忙,而且我认为我的代码由于在 try/catch 中使用了承诺 then/catch 而不干净,所以如果有更好的解决方案适合我的情况,那将是非常感谢... .
我认为错误是在 resultData
被 return 编辑到 res.send(...)
时发生的。它可能在某处有一个循环引用。为了避免这种情况,一种选择是 return 类似 JSON.stringify(resultData)
的东西,这样可以防止错误,尽管我不确定它会有多大用处....
有几点需要注意:
- 针对数据库创建新对象的建议方法是使用
.create()
方法或.build()
方法后跟.save()
,至少在 [=17 的版本 6 中是这样=] (creating new instances)。我实际上不确定如果值只是传递给构造函数会发生什么,如new Order({ productId, quantity })
,但更新数据库必须是异步的,并且对象实例化并不意味着在 javascript 中是异步的]. .catch(err => err)
可能不会按照您想要的方式处理错误。- 当
product.productStock <= 0
时,res.json(...)
的值被return编辑并存储在resultData
中。随后,resultData
在res.send(...)
中被 return 编辑,这在express.js
中是不允许的。也就是说,同一个http请求不能有两个response。 - 当需要对数据库执行一系列需要原子化的步骤时,sequelize 提供 transactions,这很有帮助。
考虑到这一点,我会尝试重构为类似下面的代码。可能还有其他方法可以改进,但至少错误应该消失,上面的一些问题将得到修复。
const sequelize = new Sequelize(/* connection string or other db options here */)
router.post('/', async (req, res) => {
const { productId, quantity } = req.body
let t = await sequelize.transaction()
try {
let order,
product
product = await Product.findOne({
where: { productId },
transaction: t
})
if (!product || product.productStock <= 0) {
await t.rollback()
res.json({
status: "failed",
message: "out of stock"
})
} else {
order = await Order.create({
productId,
quantity
}, {
transaction: t
})
await product.decrement('productStock', {
by: order.quantity,
transaction: t
})
await t.commit()
res.send({
status: "success",
data: JSON.stringify(order)
})
}
} catch (err) {
if (t) {
await t.rollback()
}
}
})