簡體   English   中英

nodejs循環中的多個http請求

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM