nodejs循环中的多个http请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19911429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
nodejs multiple http requests in loop
提问by SzymonPoltorak
I'm trying to make simple feed reader in node and I'm facing a problem with multiple requests in node.js. For example, I got table with urls something like:
我正在尝试在 node 中制作简单的提要阅读器,但我在 node.js 中遇到了多个请求的问题。例如,我得到了一个带有 url 的表,例如:
urls = [
"http://url1.com/rss.xml",
"http://url2.com",
"http://url3.com"];
Now I want to get contents of each url. First idea was to use for(var i in urls)but it's not good idea. the best option would be to do it asynchronously but I don't know how to make it.
现在我想获取每个 url 的内容。第一个想法是使用,for(var i in urls)但这不是一个好主意。最好的选择是异步执行,但我不知道如何实现。
Any ideas?
有任何想法吗?
EDIT:
编辑:
I got this code:
我得到了这个代码:
var data = [];
for(var i = 0; i<urls.length; i++){
http.get(urls[i], function(response){
console.log('Reponse: ', response.statusCode, ' from url: ', urls[i]);
var body = '';
response.on('data', function(chunk){
body += chunk;
});
response.on('end', function() {
data.push(body);
});
}).on('error', function(e){
console.log('Error: ', e.message);
});
}
Problem is that first is call line "http.get..." for each element in loop and after that event response.on('data') is called and after that response.on('end'). It makes mess and I don't know how to handle this.
问题是,首先是循环中每个元素的调用行“http.get...”,在该事件之后 response.on('data') 被调用,在 response.on('end') 之后。它弄得一团糟,我不知道如何处理。
回答by toasted_flakes
By default node httprequests are asynchronous. You can start them sequentially in your code and call a function that'll start when all requests are done. You can either do it by hand (count the finished vs started request) or use async.js
默认情况下,节点http请求是异步的。您可以在代码中按顺序启动它们并调用一个函数,该函数将在所有请求完成后启动。您可以手动完成(计算完成的请求和启动的请求)或使用 async.js
This is the no-dependency way (error checking omitted):
这是无依赖方式(省略错误检查):
var http = require('http');
var urls = ["http://www.google.com", "http://www.example.com"];
var responses = [];
var completed_requests = 0;
for (i in urls) {
http.get(urls[i], function(res) {
responses.push(res);
completed_requests++;
if (completed_requests == urls.length) {
// All download done, process responses array
console.log(responses);
}
});
}
回答by werne2j
I know this is an old question, but I think a better solution would be to use JavaScripts Promise.all():
我知道这是一个老问题,但我认为更好的解决方案是使用 JavaScripts Promise.all():
const request = require('request-promise');
const urls = ["http://www.google.com", "http://www.example.com"];
const promises = urls.map(url => request(url));
Promise.all(promises).then((data) => {
// data = [promise1,promise2]
});
回答by Adrian
You need to check that on end(data complete event) has been called the exact number of requests... Here's a working example:
您需要检查 on end(data complete event) 已被称为请求的确切数量...这是一个工作示例:
var http = require('http');
var urls = ['http://adrianmejia.com/atom.xml', 'http://twitrss.me/twitter_user_to_rss/?user=amejiarosario'];
var completed_requests = 0;
urls.forEach(function(url) {
var responses = [];
http.get(url, function(res) {
res.on('data', function(chunk){
responses.push(chunk);
});
res.on('end', function(){
if (completed_requests++ == urls.length - 1) {
// All downloads are completed
console.log('body:', responses.join());
}
});
});
})
回答by sait cihangir Aldemir
You can use any promise library with ".all" implementation. I use RSVP library, Its simple enough.
您可以使用任何具有“.all”实现的承诺库。我使用 RSVP 库,它很简单。
var downloadFileList = [url:'http://stuff',dataname:'filename to download']
var ddownload = downloadFileList.map(function(id){
var dataname = id.dataname;
var url = id.url;
return new RSVP.Promise(function(fulfill, reject) {
var stream = fs.createWriteStream(dataname);
stream.on('close', function() {
console.log(dataname+' downloaded');
fulfill();
});
request(url).on('error', function(err) {
console.log(err);
reject();
}).pipe(stream);
});
});
return new RSVP.hashSettled(ddownload);
回答by ANUPAM CHAUDHARY
The problem can be easily solved using closure. Make a function to handle the request and call that function in the loop. Every time the function would be called, it would have it's own lexical scope and using closure, it would be able to retain the address of the URL even if the loop ends. And even is the response is in streams, closure would handle that stuff too.
使用闭包可以很容易地解决这个问题。创建一个函数来处理请求并在循环中调用该函数。每次调用该函数时,它都会有自己的词法范围,并且使用closure,即使循环结束,它也能够保留 URL 的地址。即使响应是在流中,闭包也会处理这些东西。
const request = require("request");
function getTheUrl(data) {
var options = {
url: "https://jsonplaceholder.typicode.com/posts/" + data
}
return options
}
function consoleTheResult(url) {
request(url, function (err, res, body) {
console.log(url);
});
}
for (var i = 0; i < 10; i++) {
consoleTheResult(getTheUrl(i))
}

