2013-12-09 36 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