【问题标题】:Knex Transaction with PromisesKnex 承诺交易
【发布时间】:2014-05-22 07:54:31
【问题描述】:

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

在这个代码示例中:我正在做一个交易

(1) 插入 (2) 更新

我的方法是将我的数据库操作嵌套在 .then 中。 我的问题是这段代码是否偶然正确?我对 promises 和 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
});

这行得通,但我觉得我仍然做错了什么。正在寻找 cmets。

【问题讨论】:

  • 您可以尝试 1) 在 // it worked 和 // it failed cmets 所在的位置添加一些 console.logs,以及 2) 以某种方式强制插入语句失败吗?使用您当前的嵌套,仅在更新失败时调用 t.rollback,所以我想如果插入失败,它不会做正确的事情。

标签: database node.js transactions promise


【解决方案1】:

您需要从内部查询返回一个承诺,以便外部链与它链接。

您还会吞下任何错误,因为您不会重新抛出它们 - 出于这个原因,最好使用 .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
}

【讨论】:

  • 真的很有帮助,但是您没有错过第二个示例更新的交易吗?
  • 在第二个示例中,如果您要在事务中使用SELECT 查询,您将如何将它与async/await 一起使用?
  • @Juan 我也想知道更新调用是否需要交易。它应该在那里吧?
  • 我确实在需要的时候多次使用它,这里还有一堆例子newbedev.com/…
【解决方案2】:

我在这里尝试接受的答案。它给我带来了一些错误,例如“事务查询已经完成”和“数据库锁定”。答案很旧,因此可能正在使用以前的版本。我正在使用Sqlite3.34.1 和knex0.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()
}

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

【讨论】:

    猜你喜欢
    • 2018-08-13
    • 2020-05-14
    • 2019-03-04
    • 2018-11-20
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2018-05-24
    • 1970-01-01
    相关资源
    最近更新 更多