简体   繁体   English

Node.JS:for循环中的异步Postgres查询

[英]Node.JS: Asyncronous Postgres query in for loop

I want to query some data from the database, from a for loop. 我想从for循环中查询数据库中的某些数据。 The problem is, the query is processed after the end of the loop. 问题是,查询在循环结束后处理。

This code: 这段代码:

ret = [];
first = rows[0];
first.device_firsttime = first.device_lasttime;
first.alerts = [];


for(var i = 0; i < 5; i++)
{
    console.log("!"+i);
    (function(i) {
        query("SELECT EXTRACT('epoch' FROM alert_time)::integer alert_time, alert_id, alert_lat, alert_lon, alert_str, alert_cc, alert_distance FROM blitz_device_former_alerts WHERE alert_locid = $1", [first.device_locid], function(error_a,rows_a,result_a)
        {
            console.log(i+"!");
            ret.push(i);
        });
    })(i);
}

console.log("-END---"+JSON.stringify(ret));
ret.push(first);
res.end(JSON.stringify(ret));

Writing this to the console: 将此写入控制台:

!0
!1
!2
!3
!4
-END---[]
POST /userlogs 200 140.110 ms - -
0!
1!
2!
3!
4!

The correct output should be 正确的输出应该是

!0
0!
!1
1!
!2
2!
!3
3!
!4
4!
-END---[0,1,2,3,4]
POST /userlogs 200 xxx.xxx ms - -

The query is asynchronous. 该查询是异步的。 The loop doesn't wait for those queries to finish. 循环不等待这些查询完成。 It's easier to use some flow control library such as 'async'. 使用某些流控制库(例如“异步”)会更容易。

var async = require('async');
async.eachSeries([0, 1, 2, 3, 4], function(i, callback) {
  console.log("!"+i);
  query("SELECT EXTRACT('epoch' FROM alert_time)::integer alert_time, alert_id, alert_lat, alert_lon, alert_str, alert_cc, alert_distance FROM blitz_device_former_alerts WHERE alert_locid = $1", [first.device_locid], function(error_a,rows_a,result_a) {
    console.log(i+"!");
    ret.push(i);
    callback(null);  // null -> no error
  });

}, function(err) {
  console.log("-END---"+JSON.stringify(ret));
  ret.push(first);
  res.end(JSON.stringify(ret));
});

You may want to use the async library for that job: essentially it will run your functions in sequence. 您可能要为该作业使用异步库:本质上,它将按顺序运行您的函数。 It is also a good practice to use named functions, in this case a second-order function getExtractor() : a function that returns another function, usable by async . 使用命名函数也是一种好习惯,在这种情况下,使用二阶函数getExtractor() :该函数返回另一个函数,可通过async async likes to have functions that accept callbacks, which is where the result of each execution is added. async喜欢具有接受回调的函数,在函数中添加每次执行的结果。

The code would be something like this: 该代码将是这样的:

var async = require('async');
first = rows[0];
first.device_firsttime = first.device_lasttime;
first.alerts = [];

var tasks = [];    
for(var i = 0; i < 5; i++)
{
    tasks.push(getExtractor(i));
}

async.series(function(result) {
    console.log("-END---"+JSON.stringify(result));
    result.push(first);
    res.end(JSON.stringify(result));
});

function getExtractor(i) {
    return function(callback) {
        console.log("!"+i);
        query("SELECT EXTRACT('epoch' FROM alert_time)::integer alert_time, alert_id, alert_lat, alert_lon, alert_str, alert_cc, alert_distance FROM blitz_device_former_alerts WHERE alert_locid = $1", [first.device_locid], function(error_a,rows_a,result_a)
        {
            console.log(i+"!");
            return callback(null, i);
        });
    });
}

A few notes: 一些注意事项:

  • Each function pushed to the tasks array accepts a callback of the form function(error, result) . 推送到tasks数组的每个函数都接受形式为function(error, result)的回调。 The first parameter is an optional error. 第一个参数是可选错误。
  • I have not dealt with errors in the code, for simplicity, but it is important to do it. 为了简单起见,我没有处理代码中的错误,但是这样做很重要。
  • If for any reason you want to run all functions in parallel you can do it just using async.parallel() . 如果出于任何原因要并行运行所有功能,则可以使用async.parallel()
  • The final bit (when all pieces have been gathered) is executed in the callback passed to async.series() . 最后的一位(收集所有片段时)在传递给async.series()的回调中执行。
  • When async receives an array of functions, it sends to its callback an array of results. async接收到一个函数数组时,它将一个结果数组发送到其回调。 That is why we get the result automatically constructed by async . 这就是为什么我们得到async自动构造result原因。
  • You can do the same without async but frankly, the code is quite complex and I don't recommend it. 您可以在没有async的情况下执行相同的操作,但是坦率地说,代码非常复杂,我不建议这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM