【问题标题】:better solution for sequelize decrement后续减量的更好解决方案
【发布时间】:2021-05-25 20:47:47
【问题描述】:

我是续集和尝试减量的新手。我有两种型号的产品和订单,在产品中有 productStock 列,在 order 中有数量列。我想要做的是当我创建新订单时 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

(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

【问题讨论】:

    标签: node.js sequelize.js mysql2 node-mysql decrement


    【解决方案1】:

    我认为在res.send(...) 中返回resultData 时会发生错误。它可能在某处有一个循环引用。为避免这种情况,一种选择是返回 JSON.stringify(resultData) 之类的内容,这样可以防止错误发生,尽管我不确定它会有多大用处....

    有几点需要注意:

    • 针对数据库创建新对象的建议方法是使用.create() 方法或.build() 方法后跟.save(),至少在sequelize (creating new instances) 的第6 版中。实际上,我不确定如果像 new Order({ productId, quantity }) 那样将值仅传递给构造函数会发生什么,但更新数据库必须是异步的,并且对象实例化在 javascript 中并不意味着异步。
    • .catch(err =&gt; err) 可能不会按照您想要的方式处理错误。
    • product.productStock &lt;= 0时,返回res.json(...)的值,并存储在resultData中。随后,resultDatares.send(...) 中返回,这是在express.js 中不允许的。换句话说,同一个 http 请求不能有两个响应。
    • 当需要对数据库执行一系列需要原子化的步骤时,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()
            }
        }
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-20
      • 2011-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多