簡體   English   中英

Node.JS:for循環中的異步Postgres查詢

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

我想從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' 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
!1
!2
!3
!4
-END---[]
POST /userlogs 200 140.110 ms - -
0!
1!
2!
3!
4!

正確的輸出應該是

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

該查詢是異步的。 循環不等待這些查詢完成。 使用某些流控制庫(例如“異步”)會更容易。

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 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數組的每個函數都接受形式為function(error, result)的回調。 第一個參數是可選錯誤。
  • 為了簡單起見,我沒有處理代碼中的錯誤,但是這樣做很重要。
  • 如果出於任何原因要並行運行所有功能,則可以使用async.parallel()
  • 最后的一位(收集所有片段時)在傳遞給async.series()的回調中執行。
  • async接收到一個函數數組時,它將一個結果數組發送到其回調。 這就是為什么我們得到async自動構造result原因。
  • 您可以在沒有async的情況下執行相同的操作,但是坦率地說,代碼非常復雜,我不建議這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM