2014-07-05 199 views
0
var request = require('request'), 
requests = [], 
values = [], 

request("url1", function()); 

function() { 
..... 
    for (x in list){ 
    requests.push(requestFunction(x)); 
    } 
} 

requestFunction(x){ 
    request("url2", function (e,r,b) { 
    .... 
    return function(callback) { 
    values[i] = b 
    } 
    }); 
} 

async.parallel(requests, function (allResults) { 
    // values array is ready at this point 
    // the data should also be available in the allResults array 
    console.log(values); 
}); 

我是新來的節點。問題是需要調用請求來填充請求回調數組。但問題是async.parallel將在請求數組已滿並且需要運行所有回調之前運行。我在哪裏移動這個異步,以便在請求數組已滿後運行?使用之前調用的函數填充異步數組。

回答

2

異步編程完全是關於鏈接塊。這允許節點高效地運行其事件隊列,同時確保您的步驟按順序完成。例如,下面是從web應用程序我寫了一個查詢:

app.get("/admin", isLoggedIn, isVerified, isAdmin, function (req, res) { 
    User.count({}, function (err, users) { 
     if (err) throw err; 
     User.count({"verified.isVerified" : true}, function (err2, verifiedUsers) { 
      if (err2) throw err2; 
      Course.count({}, function (err3, courses) { 
       // and this continues on and on — the admin page 
       // has a lot of information on all the documents in the database 
      }) 
     }) 
    }) 
}) 

注意我是如何鏈接的功能,彼此的內部調用。只有在調用User.count({"verified.isVerified" : true}, ...)時才能調用Course.count({}, ...)。這意味着I/O永遠不會被阻止,並且在沒有所需信息的情況下永遠不會呈現頁面。

你真的沒有給出關於您的問題足夠的信息(因此有可能是一個更好的辦法來解決它),但我認爲你可以,現在,這樣做:

var request = require('request'), 
    requests = [], 
    values = [], 
    length;  // a counter to store the number of times to run the loop 

request("url1", function() { 

    length = Object.keys(list).length; 
    // referring to the list below; 
    // make sure list is available at this level of scope 

    for (var x in list){ 
     requests.push(requestFunction(x)); 
     length--; 
     if (length == 0) { 
      async.parallel(requests, function (allResults) { 
       console.log(values); // prints the values array 
      }); 
     } 
    } 
} 

function requestFunction(x) { 
    request("url2", function (e,r,b) { 
     values[i] = b; 
     return b; 
    } 
} 

我假設requestFunction()需要一段時間才能加載,這就是爲什麼async.parallelfor (var x in list)循環完成之前運行的原因。在循環結束後強制async.parallel運行,您需要一個計數器。

var length = Object.keys(list).length; 

這將返回list關聯數組(關鍵字對象)中的鍵數。現在,每次運行for循環時,都會減少length。當length == 0,然後你運行你的async.parallel過程。

編輯:你也可以寫requests.push()部分爲:

requests.push(
    (function() { 
     request("url2", function (e,r,b) { 
      values[i] = b; 
      return b; 
     } 
    })() 
); 

,我認爲它是多餘的存儲b兩個valuesrequests,但我一直是你了吧。

+0

這非常有幫助。現在我有一個問題,請求數組是未定義的。我是否在requestFunction中錯誤地返回函數? – CWon

+0

@CWon這是針對特定圖書館的嗎?無論如何,'requestFunction'並沒有什麼意義。你返回一個函數:'return function(callback){...}',但是lambda不返回任何東西。 – royhowie

+0

@CWon我在原來的答案中更改了'requestFunction',並添加了另一個推送到'requests'數組的方法。 – royhowie