node-postgres:查询不按顺序执行

时间:2016-03-06 06:47:09

标签: node.js postgresql node-postgres

我保持插入&根据条件更新2个不同文件中的代码 总是插入应首先执行然后更新。但不知何故更新首先执行然后插入

test.js:简化代码

我正在使用这些套餐:pguuid

var pg = require('pg');
var uuid = require('node-uuid').v4;
var id = uuid().toString();
var conString = 'postgres://postgres:pass@127.0.0.1:5432/testdb';

// ------INSERT
pg.connect(conString, function(err, client, done) {

    console.log('Executing Insert query');

    client.query('insert into testdb (id,data,iscancelled) values ($1,$2,$3)',[id,'hello','no'],  function(err, result) {

        done();

        if(err) { return console.error('error running query', err);  }

        console.log('finished executing Insert query');

    });
});

// ------UPDATE
pg.connect(conString, function(err, client, done) {

    console.log('Executing update query');

    client.query("update testdb set iscancelled = 'yes' where id = $1",[id],  function(err, result) {

        done();

        if(err) { return console.error('error running query', err);  }

        console.log('finished executing Update query');

    });
});

输出

tom@tom:~$node test.js
Executing Insert query
Executing update query
finished executing Update query //WHY UPDATE FINISHES FIRST
finished executing Insert query

注意:

使用async可以轻松解决此问题。但我的插入代码和更新代码位于不同的文件中,根据某些情况,更新代码可能会执行。所以不要使用异步

问题

即使插入查询首先执行为什么更新在输出中首先完成

我错过了什么东西..?

3 个答案:

答案 0 :(得分:1)

正如我已经提到的,确保 update 函数仅在 insert 函数完成后才会触发的唯一方法是在 insert中调用它函数回调。这是asynchronous programming的基础知识。

pg.connect(conString, function(err, client, done) {

    console.log('Executing Insert query');

    client.query('insert into testdb (id,data,iscancelled) values ($1,$2,$3)',[id,'hello','no'],  function(err, result) {

        done();

        if(err) { return console.error('error running query', err);  }

        console.log('finished executing Insert query');

        // ------UPDATE
        pg.connect(conString, function(err, client, done) {

            console.log('Executing update query');

            client.query("update testdb set iscancelled = 'yes' where id = $1",[id],  function(err, result) {

            done();

            if(err) { return console.error('error running query', err);  }

            console.log('finished executing Update query');

        });

    });
});

答案 1 :(得分:1)

  

让我们一步一步解决这个问题

你已经,所以不想使用async “库

解决方案1:

如果PostgreSQL更快地更新,更新将在插入之前返回结果。如果您想在完成插入后再开始执行更新查询

you should set connection pool capacity to 1.

pg.defaults.poolSize = 1

但您应该在任何pg.connect()

之前执行此操作

connect方法从客户端池中检索客户端,或者如果所有池化客户端都忙,并且池未满,则connect方法将创建一个新客户端,将其第一个参数直接传递给客户端构造函数。在任何一种情况下,只有在客户端准备发出查询或遇到错误时才会调用您提供的回调。每次调用connect时,都会调用一次回调函数。

结论:您的查询将按顺序执行。但是但此解决方案 BAD 用于扩展应用,因为始终只有一个连接为所有用户提供服务。因此,只有一个连接为一个用户服务,其他用户将不得不等待响应。

解决方案2:

您还说“我已将插入和更新代码保存在2个不同的文件中

您似乎需要设计代码,以便能够使用asynchronus库来解决此问题

答案 2 :(得分:0)

您缺少pg.connect和client.query的异步特性。对这些的调用返回一个回调,该回调在执行完成之前将控制传递给下一个表达式,因此nodejs具有非阻塞性质。如果您想确保正确的流量,请在回调成功中调用后续的流程

var pg = require('pg');
var uuid = require('node-uuid').v4;
var id = uuid().toString();

// ------INSERT
return pg.connect;

// ------UPDATE
return pg.connect;

// your calling file
var insert = require('/path/to/insertfile');
var conString = 'postgres://postgres:pass@127.0.0.1:5432/testdb';
var update = require('/path/to/updatefile');

insert(conString, function (err, client, done) {
    console.log('Executing Insert query');
    client.query('insert into testdb (id,data,iscancelled) values ($1,$2,$3)',[id,'hello','no'],  function (err, result) {
        if (err) { 
           return console.error('error running query', err);  
        }
        console.log('finished executing Insert query');

        update(conString, function (error, client, done) {
           console.log('Executing update query');

           client.query("update testdb set iscancelled = 'yes' where id = $1",[id],  function (err, result) {

              if (err) { 
                  return console.error('error running query', err);  
              }
              console.log('finished executing Update query');
              done();
          });
        });
        done();
    });    

});

但这很容易被回调地狱。所以考虑让所有异步调用返回一个promise。看看bluebird。如果您想要一个内置基于承诺的呼叫的ORM,您可以查看sequelize。它对你来说可能很方便。

它的语法很简单:

var Model1 = require('/path/to/model1');
var Model2 = require('/path/to/model2');

var insertObj = {
    "someKey": "value"
};

Model1.create(insertObj)
     .then( function (createdObj1) {
         return Model2.findOne({
             where: {
                "filter": "filterValue"
             }
         });
     })
     .then( function (documentToUpdate) {
         return documentToUpdate.update({
             "fieldToUpdate": "value"
         });  
     })
     .then( null, function (err) {
         console.log(err);
     });