2013-12-09 32 views
0

我想打一個HTTP要求在一個陣列中的每個元素,並將所有響應合併成一個單一的陣列,像這樣:node.js的:使HTTP調用在循環

result = [] ; i = 0 
for item in array 
    options = get_options(item) 
    request options, (err, res, body)-> 
    result[i++] = body 

// when all calls are done, console.log the 'result' array 

我看着異步模塊,但我不確定如何使用它。使用

+0

您可能想要使用異步庫。 – Yalamber

+0

您如何看待韓國的問題? –

+0

@askkirati,正如我在我的問題中提到的,我知道異步模塊,但我不明白如何以並行方式創建請求並將結果獲取到數組中。如果您知道如何做到這一點,請將其添加爲答案。 – tldr

回答

1

異步庫的地圖功能,您可以

var makeRequest = function(item, callback){ 
    var options = get_options(item); 
    // handle http errors and getting access to body properly 
    http.get(options,res){ 
     callback(null, res) 
    } 
} 

async.map(['item1','item2','item3'], makeRequest(item, callback), function(err, results){ 
    //check errors do stuff with results 
}); 
+0

這會給我一個請求調用的選項數組。我如何平行撥打電話? – tldr

+0

我想我已經更新它來回答你的問題。 makeRequest函數收集選項並並行地爲數組中的每個項目提出請求。然後將請求數據放入結果數組中。 – djbrick

2

試試這個,應該工作。您可能想要嘗試使用mapLimit來限制並行請求或mapSeries的順序執行。

var async = require('async'); 
var request = require('request'); 
async.map(['url1', 'url2'], function(item, callback){ 
    request(item, function (error, response, body) { 
    callback(error, body); 
    }); 
}, function(err, results){ 
    console.log(results); 
}); 

你的例子我需要看看你的get_options函數。它是同步的嗎?如果是的話,你可以做到這一點

var async = require('async'); 
var request = require('request'); 
var options; 
async.map([item1, item2], function(item, callback){ 
    options = get_options(item); 
    request(options, function (error, response, body) { 
    callback(error, body); 
    }); 
}, function(err, results){ 
    console.log(results); 
}); 

如果您get_options是異步的,接受回調做以下操作:

var async = require('async'); 
var request = require('request'); 
async.map([item1, item2], function(item, callback){ 
    get_options(item, function(err, option){ 
    if(err) { 
     callback(err); 
    } 
    else{ 
     request(options, function (error, response, body) { 
     callback(error, body); 
     }); 
    } 
    }); 
}, function(err, results){ 
    console.log(results); 
}); 
+0

得到了異步:) –

0

如果你有興趣在這裏使用的承諾是一個答案還有:

var Q = require('q'); 
var http = require('http'); 

var httpGet = function(url) { 
    var data = "", defer = Q.defer(); 
    http.get(url, function (res) { 
    var content_length = parseInt(res.headers['content-length'], 10); 
    var total_downloaded = 0; 
    if (res.statusCode !== 200) { 
     defer.reject("HTTP Error " + res.statusCode + " for " + url); 
     return; 
    } 
    res.on("error", defer.reject); 
    res.on("data", function (chunk) { 
     data += chunk; 
     total_downloaded += chunk.length; 
     var percentage = Math.floor((total_downloaded/content_length) * 100); 
     defer.notify(percentage); 
    }); 
    res.on("end", function() { defer.resolve(data); }); 
    }); 
    return defer.promise; 
} 

這使用Q promises庫。您可以這樣使用它:

var promise = httpGet("http://example.com/"); 
promise.then(function (data) { 
    // Do something with data. 
}, function (reason) { 
    // Do something with the error 
}, function (progress) { 
    // Do something with the progress update (% so far) 
}); 
+0

@sibbl:在這個例子中,爲什麼'var httpGet = function()...'首選於函數httpGet()...'我在理論上對這種差異很熟悉,但從來沒有在這個領域發現太多的不同。 – Sukima

+0

它不是。不幸的是,您必須更改至少6個字符才能進行編輯...我更願意更改此內容,因爲它根本不會更改原始內容,而不是留下「回覆」而不是「res」錯字。如果下次有更好的方法解決這個問題,我會很感激。 – sibbl

+0

對我來說似乎很合理,如果有更多理論上的原因,我只是好奇而已。但是,SO理由是有道理的。 LOLZ! – Sukima