[英]nodejs multiple http requests in loop
我正在尝试在 node 中制作简单的提要阅读器,但我在 node.js 中遇到了多个请求的问题。 例如,我得到了一个带有 url 的表,例如:
urls = [
"http://url1.com/rss.xml",
"http://url2.com",
"http://url3.com"];
现在我想获取每个 url 的内容。 第一个想法是使用for(var i in urls)
但这不是个好主意。 最好的选择是异步执行,但我不知道如何实现。
有任何想法吗?
编辑:
我得到了这个代码:
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);
});
}
问题是,首先是循环中每个元素的调用行“http.get...”,在该事件之后 response.on('data') 被调用,然后是 response.on('end')。 它弄得一团糟,我不知道如何处理。
默认情况下,节点http
请求是异步的。 您可以在代码中按顺序启动它们,并调用一个在所有请求完成后启动的函数。 您可以手动执行(计算已完成的vs已启动的请求)或使用async.js
这是无依赖方式(省略错误检查):
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);
}
});
}
我知道这是一个老问题,但我认为更好的解决方案是使用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]
});
您需要检查end
(数据完成事件)是否已被调用确切的请求数...这是一个工作示例:
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());
}
});
});
})
您可以使用任何带有“.all”实现的promise库。 我使用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);
使用闭包可以很容易地解决问题。 创建一个函数来处理请求并在循环中调用该函数。 每次调用该函数时,它都有自己的词法范围并使用闭包 ,即使循环结束,它也能保留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))
}
Promise.allSettled不会因错误而停止。 它确保您处理所有响应,即使有些响应有错误。
Promise.allSettled(promises)
.then((data) => {
// do your stuff here
})
.catch((err) => {
console.log(JSON.stringify(err, null, 4));
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.