Knex交易与承诺

dav*_*vid 13 database transactions node.js 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
});
Run Code Online (Sandbox Code Playgroud)

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

Esa*_*ija 29

您需要从内部查询返回一个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
});
Run Code Online (Sandbox Code Playgroud)

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

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
}
Run Code Online (Sandbox Code Playgroud)

  • 真的很有帮助,但是您是不是错过了有关第二个示例更新的交易? (3认同)
  • 在第二个例子中,如果你要在事务中使用一个 `SELECT` 查询,你会如何将它与 `async`/`await` 一起使用? (2认同)

Gun*_*jan 5

我正在尝试这里接受的答案。它向我抛出了一些错误,例如“事务查询已完成”和“数据库已锁定”。答案是旧的,所以可能正在使用以前的版本。我正在使用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()
}
Run Code Online (Sandbox Code Playgroud)

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