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

node-postgres : query not executing in sequence

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

test.js : 简化代码

我正在使用这些软件包:pg , uuid

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 (,,)',[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 = ",[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 可以轻松解决这个问题。但是我的插入代码和更新代码在不同的文件中,根据某些情况,更新代码可能 execute.so 不想使用异步

问题

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

我是不是漏了什么..?

正如我已经提到的,确保 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 (,,)',[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 = ",[id],  function(err, result) {

            done();

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

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

        });

    });
});

您缺少 pg.connect 和 client.query 的异步特性。对这些 return 的调用是一个回调,它在执行完成之前将控制传递给下一个表达式,因此具有 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 (,,)',[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 = ",[id],  function (err, result) {

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

});

但这很容易出现回调地狱。所以考虑让所有异步调用 return 成为一个承诺。看看bluebird. If you want an ORM that has built in promise based call, you can take a look at 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);
     });

Lets solve this question step by step

你"stated so don't want to use async"图书馆

解决方案 1:

如果 PostgreSQL 使更新更快,更新将 return 在插入之前产生结果。如果您只想在完成插入后才开始执行更新查询,那么

you should set connection pool capacity to 1.

pg.defaults.poolSize = 1

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

之前这样做

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

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

解决方案 2:

您还声明“我在 2 个不同的文件中保留了插入和更新代码

看来您需要以能够使用 asynchronus 库的方式设计代码,这解决了这个问题