Js 7如何使用异步/等待事务序列化?

Js 7和更高版本已经支持异步/等待语法?

76285 次浏览
let transaction;


try {
// get transaction
transaction = await sequelize.transaction();


// step 1
await Model.destroy({ where: {id}, transaction });


// step 2
await Model.create({}, { transaction });


// step 3
await Model.update({}, { where: { id }, transaction });


// commit
await transaction.commit();


} catch (err) {
// Rollback transaction only if the transaction object is defined
if (transaction) await transaction.rollback();
}

上面的代码在销毁调用中出错。

 await Model.destroy({where: {id}, transaction});

事务是 options 对象的一部分。

User7403683给出的答案描述了非托管事务(http://docs.sequelizejs.com/manual/tutorial/transactions.html#unmanaged-transaction-then-callback-)的异步/等待方式

异步/等待风格的托管事务可能如下所示:

await sequelize.transaction( async t=>{
const user = User.create( { name: "Alex", pwd: "2dwe3dcd" }, { transaction: t} )
const group = Group.findOne( { name: "Admins", transaction: t} )
// etc.
})

如果发生错误,事务将自动回滚。

接受的答案是“非托管事务”,这要求您显式调用 commitrollback。对于任何想要“托管交易”的人来说,这就是它的样子:

try {
// Result is whatever you returned inside the transaction
let result = await sequelize.transaction( async (t) => {
// step 1
await Model.destroy({where: {id: id}, transaction: t});


// step 2
return await Model.create({}, {transaction: t});
});


// In this case, an instance of Model
console.log(result);
} catch (err) {
// Rollback transaction if any errors were encountered
console.log(err);
}

要回滚,只需在事务函数中抛出一个错误:

try {
// Result is whatever you returned inside the transaction
let result = await sequelize.transaction( async (t) => {
// step 1
await Model.destroy({where: {id:id}, transaction: t});


// Cause rollback
if( false ){
throw new Error('Rollback initiated');
}


// step 2
return await Model.create({}, {transaction: t});
});


// In this case, an instance of Model
console.log(result);
} catch (err) {
// Rollback transaction if any errors were encountered
console.log(err);
}

如果任何代码在事务块中抛出错误,则会自动触发回滚。

async () => {
let t;


try {
t = await sequelize.transaction({ autocommit: true});


let _user = await User.create({}, {t});


let _userInfo = await UserInfo.create({}, {t});


t.afterCommit((t) => {
_user.setUserInfo(_userInfo);
// other logic
});
} catch (err) {
throw err;
}
}

如果启用了 CLS,Sequelize 可以使用它来保存您的交易对象,并自动将其传递给 continuation-passing周期内的所有查询。

设置:

import { Sequelize } from "sequelize";
import { createNamespace } from "cls-hooked"; // npm i cls-hooked


const cls = createNamespace("transaction-namespace"); // any string
Sequelize.useCLS(cls);


const sequelize = new Sequelize(...);

用法:

const removeUser = async (id) => {
await sequelize.transaction(async () => { // no need `async (tx)`
await removeUserClasses(id);
await User.destroy({ where: { id } }); // will auto receive `tx`
});
}


const removeUserClasses = async (userId) => {
await UserClass.destroy({ where: { userId } }); // also receive the same transaction object as this function was called inside `sequelize.transaction()`
await somethingElse(); // all queries inside this function also receive `tx`
}

它是如何工作的?

来自 Sequelize 源代码: github.com/sequelize

检查并将事务保存到 CLS

if (useCLS && this.sequelize.constructor._cls) {
this.sequelize.constructor._cls.set('transaction', this);
}

从 CLS 检索事务并设置为选项

if (options.transaction === undefined && Sequelize._cls) {
options.transaction = Sequelize._cls.get('transaction');
}

延伸阅读:

  1. Sequelize: 自动将事务传递给所有查询
  2. CLS 上钩了
  3. 异步钩子

试试这个

const transaction = await sequelize.transaction({ autocommit: false });
try {
await Model.create(data, {transaction})
} catch (e) {
if (transaction) await transaction.rollback();
next(e);
response.status(500).json({ error: e });
}


if (transaction) {
await transaction.commit();
}