Knex交易与承诺

时间:2014-04-09 08:36:40

标签: database node.js transactions promise

我得到了正确的输出,实际上,这两个操作被视为单个事务单元;如果一个失败,那么两个都失败了。

在此代码示例中:我正在进行

的事务

(1)插入 (2)更新

我接近它的方法是将我的数据库操作嵌套在.then中。 我的问题是,这个代码是偶然的吗?我是承诺和knex的新手。

knex.transaction(function(t) {
   knex('foo')
   .transacting(t)
   .insert({id:"asdfk", username:"barry", email:"barry@bar.com"})
   .then(function() {
       knex('foo')
       .where('username','=','bob')
       .update({email:"bob@foo.com"})
       .then(t.commit, t.rollback)
   })
})
.then(function() {
 // it worked
},
function() {
 // it failed
});

这很有效,但我觉得我还在做错事。寻找意见。

2 个答案:

答案 0 :(得分:26)

您需要从内部查询返回一个promise,以便将外链与之链接。

你也可以吞下任何错误,因为你不会重新抛出它们 - 因为这样可以更好地使用.catch()因为它会使正在发生的事情变得更加清晰 - 这就是正常的try-catch陈述。

knex.transaction(function(t) {
   return knex('foo')
   .transacting(t)
   .insert({id:"asdfk", username:"barry", email:"barry@bar.com"})
   .then(function() {
        return knex('foo')
           .where('username','=','bob')
           .update({email:"bob@foo.com"});
   })
   .then(t.commit)
   .catch(function(e) {
        t.rollback();
        throw e;
   })
})
.then(function() {
 // it worked
})
.catch(function(e) {
 // it failed
});

为了更好地理解它,这里是正在模拟的同步版本":

try {
    var t = knex.transaction();
    try {
        knex("foo")
            .transacting(t)
            .insert({id:"asdfk", username:"barry", email:"barry@bar.com"});
        knex("foo")
            .where('username','=','bob')
            .update({email:"bob@foo.com"});
        t.commit();
    }
    catch (e) {
        t.rollback();
        // As you can see, if you don't rethrow here
        // the outer catch is never triggered
        throw e;
    }
    // It worked
}
catch (e) {
    //It failed
}

答案 1 :(得分:1)

我在这里尝试接受的答案。它向我抛出了一些错误,例如“事务查询已经完成”和“数据库锁定”。答案很旧,因此可能正在使用以前的版本。我正在使用 Sqlite3.34.1knex0.95.4。该代码对我进行了一些调整。添加在此线程中,它可以帮助某人。

async function process() {
    await knex.transaction(function(t) {
        return knex('foo')
        .transacting(t)
        .insert({id:"asdfkg", username:"bob", email:"bob@bar.com"})
        .then(function() {
            return t('foo').insert({id:"abcd", username:"john", email:"john@bar.com"})
        })
        .then(function() {
            return t('foo')
            .where('username','=','bob')
            .update({email:"bob@foo.com"});
        })
    })
    .then(function() {
    console.log("it worked")
    })
    .catch(function(e) {
    console.log(e)
    console.log("It failed")
    });
    knex.destroy()
}

我认为,回滚和提交是由它自己处理的,我们不必明确指定。