【问题标题】:Can sequelize.transaction() take async function as callback?sequelize.transaction() 可以将异步函数作为回调吗?
【发布时间】:2019-11-05 17:45:23
【问题描述】:

因此,阅读Instance 上的 Sequelize 文档以及有关 transactions 的文档,sequelize.transaction()autoCallback 函数作为参数。文档说:

回调是用事务对象调用的,应该返回 一个承诺。如果 promise 得到解决,则事务提交;如果 promise 拒绝,事务回滚

但是我计划在事务内部做很多事情,我想避免回调地狱。所以我试着做

try {
    let result = sequelize.transaction({
            isolationLevel: 'SERIALIZABLE'
        }, async t => {
            // code to run here with await
            let var1 = await Model.find({ transaction: t });
            let var2 = await Model.find({ transaction: t });

            if (var1.id === 1)
                return "Whatever result";
            else
                throw new Error("Something wicked");
        }
    )});

    // Whatever result
    console.log(result);
}catch(e){
    // Something wicked
}

这似乎工作得很好。但它完全没有记录,我还没有看到有人使用它。可以吗,还是我会遇到随机问题?

【问题讨论】:

  • 不确定您所说的“完全无证”是什么意思。文档说“应该返回一个承诺”,而您使用的是 async function,所以一切都很好?
  • @Bergi 是的,我希望一切都好。我只是要求确认。如果我理解正确,我不能从异步回调函数返回一个承诺(如 return Model.find()),但我必须始终返回一个值本身(如 return await Model.find()),对吗?
  • @michnovka 每个异步函数都会返回一个承诺。如果 Model.find 返回一个 promise,那么 return Model.find()return await Model.find() 之间没有显着差异。

标签: javascript node.js async-await sequelize.js


【解决方案1】:

正如 @Bergi@Nicholas Tower 在 cmets 中指出的那样:

由于异步函数总是返回承诺,而回调函数应该返回承诺,这是一个相当直截了当的答案。

是的,可以使用。

【讨论】:

    【解决方案2】:

    如果您想使用直接 async/await,请参见下文。您也没有将事务(代码中的t)传递给查询,因此他们不会使用它 - 您必须在transaction 选项中显式传递它。如果您在提交事务后进行任何更改,如果有任何错误,则随后将其回滚。您还可以通过与Promise.all() 同时运行查询来改进您的代码。

    // define outside the try/catch so you can rollback if needed
    let transaction;
    let result;
    try {
        transaction = await sequelize.transaction({ isolationLevel: 'SERIALIZABLE' });
    
        // run concurrently with Promise.all()
        const [ var1, var2 ] = await Promise.all([
           // don't await here, but you have to pass the transaction
           Model.findByPk({ transaction }),
           Model.findOne({ transaction }), // ditto
        ]);
    
        if (var1.id === 1) {
           result = "Whatever result";
        } else {
           throw new Error("Something wicked");
        }
        // if you need to commit anything...
        // await transaction.commit();
    } catch(err) {
        /* if you need to roll back anything...
        if (transaction) {
           await transaction.rollback();
        }
        */
        console.log(err);
    }
    return result;
    

    【讨论】:

    • 感谢您的回复,但即使您的解决方案确实有效,我的也是。但是不提供事务函数回调,需要手动调用commit()和rollback()。在为函数提供回调的情况下,这将由 sequelize 自动处理。还是谢谢
    • @michnovka 事务没有被传递给查询,所以它没有被使用。不过,您的答案是正确的。
    • @michnovka 提交和回滚将自动发生,但我发现这不是生产应用程序的最佳实践,因为最好控制回滚发生的时间点,以防您需要在之后执行任何操作,但那是并非所有用例都如此,因此在示例中已将其注释掉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    • 1970-01-01
    • 2014-06-14
    • 2018-06-26
    • 2021-12-08
    • 2011-12-30
    相关资源
    最近更新 更多