Javascript Node.JS:for循环中的异步Postgres查询
我想从数据库、for循环中查询一些数据。问题是,查询是在循环结束后处理的 此代码:Javascript Node.JS:for循环中的异步Postgres查询,javascript,node.js,loops,asynchronous,Javascript,Node.js,Loops,Asynchronous,我想从数据库、for循环中查询一些数据。问题是,查询是在循环结束后处理的 此代码: 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'
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));
正确的输出应该是
!0
0!
!1
1!
!2
2!
!3
3!
!4
4!
-END---[0,1,2,3,4]
POST /userlogs 200 xxx.xxx ms - -
查询是异步的。循环不会等待这些查询完成。使用诸如“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));
});
您可能希望将库用于该作业:本质上,它将按顺序运行您的函数。使用命名函数也是一种很好的做法,在本例中是二阶函数getExtractor:一个返回另一个函数的函数,可供异步使用。async喜欢使用接受回调的函数,回调是每次执行结果的添加位置
代码如下所示:
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);
});
});
}
请注意:
推送到tasks数组的每个函数都接受functionerror、result形式的回调。第一个参数是可选错误。
为了简单起见,我没有处理代码中的错误,但这样做很重要。
如果出于任何原因,您希望并行运行所有函数,则可以使用async.parallel。
收集所有片段后的最后一位在传递给async.series的回调中执行。
当async收到一个函数数组时,它会向其回调函数发送一个结果数组。这就是为什么我们会得到由async自动构造的结果。
不使用async也可以这样做,但坦率地说,代码非常复杂,我不推荐使用它。
谢谢我只是尝试了一个丑陋的递归函数,但这更简单。
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);
});
});
}