sequelize.transaction() 可以将异步函数作为回调吗?
Posted
技术标签:
【中文标题】sequelize.transaction() 可以将异步函数作为回调吗?【英文标题】:Can sequelize.transaction() take async function as callback? 【发布时间】: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()
之间没有显着差异。
【参考方案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 提交和回滚将自动发生,但我发现这不是生产应用程序的最佳实践,因为最好控制回滚发生的时间点,以防您需要在之后执行任何操作,但那是并非所有用例都如此,因此在示例中已将其注释掉。以上是关于sequelize.transaction() 可以将异步函数作为回调吗?的主要内容,如果未能解决你的问题,请参考以下文章