简体   繁体   中英

Knex Transaction with Promises

I am getting the correct output, and indeed, these two operations are being treated as a single transactional unit; where if one fails, both fail.

In this code example: i am doing a transaction of

(1) insert (2) update

The way I approach it is to nest my db operations inside the .then. My question is if this code is correct by accident? i am new to promises and 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
});

This works, but I feel like I am doing something wrong still. Looking for comments.

You need to return a promise from the inner query in order for the outer chain to be chained with that.

You also swallow any errors because you don't rethrow them - it's better to use .catch() for this reason because it makes it more clearer what is happening - that is what would happen with normal try-catch statement.

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
});

To understand it better, here's the synchronous version that is being "emulated":

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
}

I was trying out the accepted answer here. It was throwing me some errors like "Transaction query is already complete" and "Database locked". The answer is old, so might be working with previous version. I am using Sqlite3.34.1 and knex0.95.4 . The code worked for me with some tweaks. Adding in this thread, It could help someone.

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()
}

I think, rollback and commit is taken care by its own, we wont have to specify it explicitly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM