Sails.js best practice in using transactions with promises (Postgres)

后端 未结 2 1221
囚心锁ツ
囚心锁ツ 2021-02-01 06:51

I\'m using sails 0.9.16 with Postgres and my question is: what is the best way to execute transaction using current API with promises? May be there is something better than:

相关标签:
2条回答
  • 2021-02-01 07:11

    I'm currently using this exact workflow. For executing one query with promises do this:

    Model
     .query(params)
     .then(function(result){
     //act on result
     })
     .catch(function(error){
     //handle error
     })
     .done(function(){
     //clean up
     });
    

    To execute multiple queries in parallel, do this:

    var Promise = require('q');
    
    Promise.all([
    
        User.findOne(),
        AnotherModel.findOne(),
        AnotherModel2.find()
    
    ])
    .spread(function(user,anotherModel,anotherModel2){
        //use the results
    })
    .catch(function(){
        //handle errors
    })
    .done(function(){
        //clean up
    });
    

    If you're trying to avoid nesting in your code:

    Model
    .query(params)
    .then(function(result){//after query #1
        //since you're returning a promise here, you can use .then after this
        return Model.query();
    })
    .then(function(results){//after query#2
        if(!results){
            throw new Error("No results found in query #2");
        }else{
            return Model.differentQuery(results);
        }
    
    })
    .then(function(results){
    //do something with the results
    })
    .catch(function(err){
        console.log(err);
    })
    .done(function(){
        //cleanup
    });
    

    Note: currently, waterline uses Q for promises. There is a pull request to switch waterline from Q to bluebird here: waterline/bluebird

    When I answered this question, I'd yet to take the database class in college, so I didn't know what a transaction was. I did some digging, and bluebird allows you to do transactions with promises. The only problem is, this isn't exactly built into sails since it's some what of a special use case. Here's the code bluebird provides for this situation.

    var pg = require('pg');
    var Promise = require('bluebird');
    Promise.promisifyAll(pg);
    
    function getTransaction(connectionString) {
        var close;
        return pg.connectAsync(connectionString).spread(function(client, done) {
            close = done;
            return client.queryAsync('BEGIN').then(function () {
                return client;
            });
        }).disposer(function(client, promise) {
            if (promise.isFulfilled()) {
                return client.queryAsync('COMMIT').then(closeClient);
            } else {
                return client.queryAsync('ROLLBACK').then(closeClient);
            }
            function closeClient() {
                if (close) close(client);
            }
        });
    }
    
    exports.getTransaction = getTransaction;
    
    0 讨论(0)
  • 2021-02-01 07:13

    The best way to deal with transactions is when they are wrapped properly by a promise library, because transaction logic maps perfectly into the promise event chain, one doesn't have to worry about when to do COMMIT or ROLLBACK, as it happens automatically.

    Here's a complete example of how it works with pg-promise library:

    var pgp = require('pg-promise')(/*options*/);
    
    var cn = "postgres://username:password@host:port/database";
    var db = pgp(cn); // database instance;
    
    db.tx(t => {
        // BEGIN has been executed
        return t.batch([
            t.one("insert into users(name) values($1) returning id", 'John'),
            t.one("insert into users(name) values($1) returning id", 'Mike')
        ]);
    })
        .then(data => {
            // COMMIT has been executed
            console.log(data[0].id); // print id assigned to John;
            console.log(data[1].id); // print id assigned to Mike;
        })
        .catch(error => {
            // ROLLBACK has been executed
            console.log(error); // print why failed;
        });
    
    0 讨论(0)
提交回复
热议问题