Javascript Sails.js使用承诺交易的最佳实践(Postgres)

Javascript Sails.js使用承诺交易的最佳实践(Postgres),javascript,node.js,sails.js,waterline,Javascript,Node.js,Sails.js,Waterline,我在Postgres中使用sails 0.9.16,我的问题是:使用当前API和承诺执行事务的最佳方式是什么?也许有比以下更好的方法: Model.query('BEGIN TRANSACTION', function (err) { if (err) { next(err); } else { Model .create(...) .(function (value) {

我在Postgres中使用sails 0.9.16,我的问题是:使用当前API和承诺执行事务的最佳方式是什么?也许有比以下更好的方法:

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

谢谢你的帮助

我目前使用的正是这个工作流。要使用承诺执行一个查询,请执行以下操作:

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表示承诺。此处有一个将水线从Q切换到bluebird的拉动请求:

当我回答这个问题时,我还没有参加大学的数据库课程,所以我不知道事务是什么。我做了一些挖掘,蓝鸟允许你做承诺交易。唯一的问题是,这并没有完全内置到sail中,因为这是一个特殊的用例。以下是蓝鸟为这种情况提供的代码

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;

处理事务的最佳方法是使用承诺库正确包装事务,因为事务逻辑完美地映射到承诺事件链中,因此不必担心何时执行
提交
回滚
,因为这是自动发生的

下面是一个完整的示例,说明它如何与库一起工作:


你能给蓝知更鸟一个等价物吗,因为水线已经移到了bluebird@lujaw蓝鸟等价物的代码应该完全相同,因为它们都遵守A+承诺规范。@aclave1在第三个示例中,我如何才能在第二个
然后
到第三个
然后
中返回两个对象或变量。我指的是第一个查询的结果和第二个查询的另一个结果,然后在第三个
中接收这些结果?我希望能解释一下。提前谢谢@Lexynux您需要了解Bluebird的Promise.Join(result1,result2)、spread(function(result1,result2){})或Promise.bind(),具体取决于您的用例您有什么例子吗?我的代码看起来像这样,但不起作用!在SailsJS中使用这种逻辑看起来很棒,但是我怎么知道什么时候使用承诺,什么时候使用简单代码呢?简单代码是指回调吗?代码和库的异步特性决定了应该使用什么。但我已经读到,承诺是最常用的,我们需要有许多嵌套回调才能获得干净的代码。这是真的吗?@AlexVentura no,promises是Node.js中异步编程的新标准。像ES6生成器和ES7异步/等待之类的新东西会自动与promise标准配合使用。看。好吧,在任何情况下使用回调都比使用回调好吗?嘿,你是如何解决这个问题的,或者哪种方法对你来说是最好的?因为Sails postgres adapter为每个查询拉/创建新连接,我最终修改了适配器:
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;
    });