我已经看了好几天了,我还没有得到任何合理的解释。所以,快速背景:我正在使用bookshelfjs,我想使用事务来执行3次插入,并在保存时添加一些额外的引用。为了按照我想要的方式工作,我使用了蓝鸟Promise。
router.get('/transaction', function(req, res){
bookshelf.transaction(function(t){
return Promise.all([
//this block is part of transaction!
new Participant({name: 'Transaction John'}).save(null, {transacting: t}),
new Participant({name: 'Transaction Doe'}).save(null, {transacting: t}),
new Town({town_number: 1000, town_title: 'LA'}).save(null, {transacting: t})
]).spread(function(p1, p2, t1){
return Promise.all([
/*
this block, however, is not. second address save fails, because I use "p4.get('id')" which does not exists
the first address is saved, the second is not; but since I use transactions, nothing should be saved!
*/
new Address({
house_number: 3,
street_name: 'Transaction street name',
town_id: t1.get('id'),
participant_id: p1.get('id')
}).save(null, {transacting: t}),
new Address({
house_number: 3,
street_name: 'Transaction street name 2',
town_id: t1.get('id'),
participant_id: p4.get('id')
}).save(null, {transacting: t})
]);
});
}).then(function(){
res.json('success');
}).catch(function(error){
console.log('error');
res.json(error);
});
});
以下是对上述代码的查询:
{ __cid: '__cid1', sql: 'begin transaction;' }
{ __cid: '__cid1',
method: 'insert',
options: undefined,
bindings: [ 'Transaction John' ],
sql: 'insert into "participants" ("name") values (?)' }
{ __cid: '__cid1',
method: 'insert',
options: undefined,
bindings: [ 'Transaction Doe' ],
sql: 'insert into "participants" ("name") values (?)' }
{ __cid: '__cid1',
method: 'insert',
options: undefined,
bindings: [ 1000, 'LA' ],
sql: 'insert into "towns" ("town_number", "town_title") values (?, ?)' }
[ReferenceError: p4 is not defined]
{ __cid: '__cid1', sql: 'rollback;' }
{ __cid: '__cid1',
method: 'insert',
options: undefined,
bindings: [ 3, 1, 'Transaction street name', 1 ],
sql: 'insert into "addresses" ("house_number", "participant_id", "street_name"
, "town_id") values (?, ?, ?, ?)' }
从上面的代码中可以看出,回滚发生,这符合上面的代码,但在回滚后,还有一个额外的插入。这不是应该发生的事情。
为什么Promise.all在代码的第一部分工作,而在第二部分它看起来好像不是?有没有错误或者我没有正确理解某些内容?
感谢您的回复!
答案 0 :(得分:4)
正如Bookshelf.js开发人员所说:
基本上交易与promise.all
完美搭配
据推测,新版本的Bookshelf.js正在开发中,并承诺为交易提供更好的支持:https://github.com/tgriesser/knex/pull/786