Подтвердить что ты не робот

Наилучшая практика Sails.js при использовании транзакций с promises (Postgres)

Я использую паруса 0.9.16 с Postgres, и мой вопрос: какой лучший способ выполнить транзакцию с использованием текущего API с помощью promises? Может быть, есть что-то лучше, чем:

    Model.query('BEGIN TRANSACTION', function (err) {
      if (err) {
        next(err);
      } else {
        Model
          .create(...)
          .(function (value) {
            return [value, RelatedModel.create(...).then(...)];
          })
          .fail(function (err) {
            Model.query('ROLLBACK');
            next(err);
          })
          .spread(function (...) {
            Model.query('COMMIT')
            next(...);
          })
      }
    })

Спасибо за помощь!

4b9b3361

Ответ 1

В настоящее время я использую этот точный рабочий процесс. Для выполнения одного запроса с помощью promises выполните следующее:

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

Чтобы выполнить несколько запросов параллельно, сделайте следующее:

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

Если вы пытаетесь избежать вложения в свой код:

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

Примечание: В настоящее время ватерлиния использует Q для promises. Существует запрос на перенос для переключения ватерлинии от Q до голубой птицы здесь: ватерлиния/синяя птица

Когда я ответил на этот вопрос, я бы еще не взял класс базы данных в колледже, поэтому я не знал, что такое транзакция. Я сделал рытье, а bluebird позволяет делать транзакции с promises. Единственная проблема заключается в том, что это не совсем встраивается в паруса, поскольку некоторые из них относятся к специальному варианту использования. Здесь код bluebird обеспечивает эту ситуацию.

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;

Ответ 2

Лучший способ справиться с транзакциями - это то, что они надлежащим образом завертываются библиотекой обещаний, потому что логика транзакций идеально вписывается в цепочку событий обещаний, не нужно беспокоиться о том, когда делать COMMIT или ROLLBACK, поскольку это происходит автоматически.

Вот полный пример того, как он работает с pg-promise:

var pgp = require('pg-promise')(/*options*/);

var cn = "postgres://username:[email protected]: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;
    });