nodejs循环中的多个http请求

Szy*_*rak 35 javascript node.js

我正在尝试在节点中创建简单的feed阅读器,我在node.js中遇到了多个请求的问题.例如,我得到的表格如下:

urls = [
"http://url1.com/rss.xml",
"http://url2.com",
"http://url3.com"];
Run Code Online (Sandbox Code Playgroud)

现在我想获取每个网址的内容.第一个想法是使用,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);
});
}
Run Code Online (Sandbox Code Playgroud)

问题是,首先是循环中每个元素的调用行"http.get ...",然后在该事件之后调用response.on('data')并在该response.on('end')之后调用.它变得一团糟,我不知道如何处理这个问题.

toa*_*kes 39

默认情况下,节点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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 阿德里安的评论非常重要.请注意,这个答案**并不意味着任何这些请求**已经完成**.通过这个解决方案,你只知道'***'已经'发送'并且迭代结束了. (6认同)
  • 实际上,它现在的方式,它会说它在发送最后一个请求时是完整的,但不是在所有请求都完成时.我回答了我最终要解决的问题. (5认同)

小智 35

我知道这是一个老问题,但我认为更好的解决方案是使用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]
});
Run Code Online (Sandbox Code Playgroud)

  • 为什么会更好?一点点解释都会让它变得更好! (7认同)
  • 自 2020 年 2 月 11 日起,请求已完全弃用。- https://github.com/request/request-promise (2认同)

Adr*_*ian 24

你需要检查on 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());
      }      
    });
  });
})
Run Code Online (Sandbox Code Playgroud)