-1

我将插入和更新代码保存在 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

笔记 :

这个问题可以通过使用异步轻松解决。但是我的插入代码和更新代码在不同的文件中,根据某些情况更新代码可能会执行。所以不想使用异步

问题

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

我错过了什么..?

4

3 回答 3

1

正如我已经提到的,确保只有在插入函数完成 后才会触发更新函数的唯一方法是在插入函数回调中调用它。这就是异步编程的基础。

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

        });

    });
});
于 2016-03-06T09:35:21.890 回答
1

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

已经过时了,所以不想使用async

解决方案1:

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

您应该将连接池容量设置为 1。

pg.defaults.poolSize = 1

但你应该在任何之前这样做pg.connect()

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

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

解决方案 2:

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

看起来您需要以能够使用异步库的方式设计代码,从而解决此问题

于 2016-03-19T11:03:51.027 回答
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 的调用的 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);
     });
于 2016-03-06T09:35:42.407 回答