Node.js 7及更高版本已经支持async / await语法。我应该如何使用asquel / await和sequelize Transactions?
答案 0 :(得分:90)
let transaction;
try {
// get transaction
transaction = await sequelize.transaction();
// step 1
await Model.destroy({where: {id}, transaction});
// step 2
await Model.create({}, {transaction});
// commit
await transaction.commit();
} catch (err) {
// Rollback transaction if any errors were encountered
if (err) await transaction.rollback();
}
答案 1 :(得分:23)
接受的答案是“非托管交易”,要求您明确调用rollback
和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);
}
要回滚,只需在事务函数中抛出一个错误:
$(document).ready(function($) {
$( "#accordion").on('click','.accordion-heading', function (e) {
$return = true;
if($(this).next('div').is(':visible')== false) $return = false;
$( "#accordion .panel2").slideUp();
$("#accordion .accordion-heading").removeClass('active');
$(this).next('div').stop(true,false).slideDown();
$(this).addClass('active');
return $return;
});
});
如果任何在事务块中抛出错误的代码,则会自动触发回滚。
答案 2 :(得分:5)
user7403683给出的答案描述了非托管事务的异步/等待方式(http://docs.sequelizejs.com/manual/tutorial/transactions.html#unmanaged-transaction-then-callback-)
async / await样式中的托管事务可能如下所示:
await sequelize.transaction( async t=>{
const user = User.create( { name: "Alex", pwd: "2dwe3dcd" }, { transaction: t} )
const group = Group.findOne( { name: "Admins", transaction: t} )
// etc.
})
如果发生错误,则会自动回滚事务。
答案 3 :(得分:4)
上面的代码在销毁调用中有错误。
await Model.destroy({where: {id}, transaction});
交易是期权对象的一部分。
答案 4 :(得分:0)
对于上述user7403683解决方案的测试范围,请考虑使用 raiserror('msg or var',0,0) with nowait;
和sequelize-mock
:
sinon
成功交易:
import SequelizeMock from 'sequelize-mock';
import sinon from 'sinon';
sandbox.stub(models, 'sequelize').returns(new SequelizeMock());
或交易失败:
sandbox.stub(model.sequelize, 'transaction')
.resolves({commit() {}});
and stub everything in the transaction block
commit() {} provides stubbing of transaction.commit(),
otherwise you'll get a "method does not exist" error in your tests
测试sandbox.stub(models.sequelize, 'transaction').resolves({rollback() {}});
to cover transaction.rollback()
逻辑。
答案 5 :(得分:0)
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;
}
}
答案 6 :(得分:0)
如果在项目中启用了CLS,则Sequelize可以使用它保留事务对象并将其传递给<template>
<div class="subscription">
<div class="email_field">
<input
class="email_subscription"
type="email"
v-model="postEmail"
name="email_subscription"
placeholder="Email address here"
/>
</div>
<div class="submit_email">
<input type="submit" class="button_submit" @click="submitEmail()" value="Submit" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
postEmail: null,
language: "en",
};
},
methods: {
submitEmail() {
axios
.post(
"https://my_api.com/registrations?access_token=my_api_key",
{
language: this.language,
user_email: this.postEmail,
auth: {
username: "username",
password: "password"
}
}
)
.then(response => {
// console.log(response);
})
.catch(function(error) {});
}
}
};
</script>
周期内的所有查询。
设置:
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(...);
它如何工作?
从Sequelize源代码中:const removeUser = async (id) => {
await sequelize.transaction(async () => { // no need `async (tx)`
await removeClasses(id);
await User.destroy({ where: { id } }); // will auto receive `tx`
});
}
const removeClasses = 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`
}
Check and save transaction to CLS
github.com/sequelize
Retrieve transaction from CSL and set to options
if (useCLS && this.sequelize.constructor._cls) {
this.sequelize.constructor._cls.set('transaction', this);
}
了解详情: