[英]Requesting RSS feeds from two web sites in Node.JS
我有一個Node.JS服務器,它從兩個Web服務器請求數據: bbc.co.uk和sky.com 。 然后解析RSS提要,並且用戶看到兩個列表:來自BBC和來自天空。
這是代碼。
var feed = require('feed-read');
var http = require('http');
var async = require('async');
var request = require('request');
var LIMIT = 10;
var UNABLE_TO_CONNECT = "Unable to connect.";
var BBC_URL = 'http://feeds.bbci.co.uk/news/rss.xml';
var SKY_URL = 'http://news.sky.com/feeds/rss/home.xml';
var server = http.createServer(onRequest);
server.listen(9000);
function onRequest(req, res) {
res.writeHead(200, {
'Content-Type' : 'text/html; charset=utf-8'
});
async.parallel([ function(callback) {
feed(BBC_URL, onRssFetched);
// TODO: where to call callback()?
}, function(callback) {
feed(SKY_URL, onRssFetched);
// TODO: where to call callback()?
} ], function done(err, results) {
console.log("Done");
if (err) {
throw err;
}
});
}
function onRssFetched(err, articles) {
console.log("RSS fetched");
var html = [];
if (err) {
html.push("<p>", UNABLE_TO_CONNECT = "</p>");
} else {
html.push("<ol>");
var i = 0;
articles.forEach(function(entry) {
if (i == LIMIT) {
return;
}
html.push("<li><a href='" + entry.link + "'>" + entry.title
+ "</a></li>");
i++;
});
}
console.log(html.join(""));
}
現在我不知道如何將結果添加到網頁。 如果我調用callback()
調用后立即feed
的方法, callback()
將無需等到執行feed
已完成其工作。 另一方面,我無法將callback
傳遞給feed
。 也許這種方法是錯誤的,我還需要一些其他模塊來進行RSS解析。
@Maksim我知道您的原始問題包括異步模塊,但提出了另一種選擇:
為什么不將 每篇文章 流式傳輸到客戶端,而不是在發送響應之前等待所有 RSS源返回...?
通過使用async.parallel,您告訴節點:
“ 等到我們得到 所有 這些新聞服務 的回復
並且只有 這樣 (將文章組合成) 對客戶 的 單一 回應 ...“
當您等待所有響應(來自RSS新聞服務)時,這會占用每個連接客戶端的內存...... 浪費 。
所以我寫了我的答案而不訴諸異步 。
並且,而不是等待年齡 (而async將所有的feed合並為一個),
一旦第一個 RSS提要返回,客戶端就會看到新聞!
var feed = require('feed-read'), // require the feed-read module
http = require("http"),
urls = [
"http://feeds.bbci.co.uk/news/rss.xml",
"http://news.sky.com/feeds/rss/home.xml",
"http://www.techmeme.com/feed.xml"
]; // Example RSS Feeds
http.createServer(function (req, res) {
// send basic http headers to client
res.writeHead(200, {
"Content-Type": "text/html",
"Transfer-Encoding": "chunked"
});
// setup simple html page:
res.write("<html>\n<head>\n<title>RSS Feeds</title>\n</head>\n<body>");
// loop through our list of RSS feed urls
for (var j = 0; j < urls.length; j++) {
// fetch rss feed for the url:
feed(urls[j], function(err, articles) {
// loop through the list of articles returned
for (var i = 0; i < articles.length; i++) {
// stream article title (and what ever else you want) to client
res.write("<h3>"+articles[i].title +"</h3>");
// check we have reached the end of our list of articles & urls
if( i === articles.length-1 && j === urls.length-1) {
res.end("</body>\n</html>"); // end http response
} // else still have rss urls to check
} // end inner for loop
}); // end call to feed (feed-read) method
} // end urls for loop
}).listen(9000);
主要優勢 :
有關此解決方案的更多詳細信息/說明
請參閱: https : //github.com/nelsonic/node-parse-rss
不,你不需要另一個圖書館。 但您需要做的是將callback
交給您的feed
函數而不是onRssFetched
。 這樣,使用result
變量將單個RSS提要移交給async.parallel
調用中的最終回調。
在這個變量中,您可以同時訪問這兩個RSS源,並且可以對它們執行任何操作。
所以,基本上你的邏輯需要是:
async.parallel({
bbc: function (callback) {
feed(BBC_URL, callback);
},
sky: function (callback) {
feed(SKY_URL, callback);
}
}, function (err, result) {
if (err) {
// Somewhere, something went wrong…
}
var rssBbc = result.bbc,
rssSky = result.sky;
// Merge the two feeds or deliver them to the client or do
// whatever you want to do with them.
});
就是這樣:-)。
為了放大@nelsonic的答案(足以讓我覺得這保證了它自己的答案), feed-parse
已經異步處理。 從本質上講,它仍然在http.request上運行。 如果你查看代碼,你會看到你甚至可以直接傳遞一個URL數組,它會遍歷它們,但是它使用了更多的“async.eachSeries”方法,其中下一個調用只發生在前一個調用之后完成,看起來不是你想要的。
如果你真的想在處理之前等待調用先完成,那么你最好異步緩沖數據,然后使用下划線的_.after()
在所有URL完成后運行。
但是很可能,你真正想做的事情(除非你只是尋找一個嘗試異步的例子)是@ nelsonic的回答。
理想情況下,我會流式傳輸rss數據,而不是聚合在內存中。 @nelsonic已經解釋了解決這個問題的正確方法。
不過,如果我們要讓您的代碼運行,請考慮以下代碼:
var util = require('util');
var http = require('http');
var async = require('async');
var feed = require('feed-read');
var request = require('request');
var LIMIT = 10;
var UNABLE_TO_CONNECT = 'Unable to connect.';
var BBC_URL = 'http://feeds.bbci.co.uk/news/rss.xml';
var SKY_URL = 'http://news.sky.com/feeds/rss/home.xml';
var server = http.createServer(onRequest);
server.listen(9000);
function onRequest(req, res) {
util.log('Request recieved!');
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8'
});
async.parallel({
bbc: function (callback) {
feed(BBC_URL, function (err, articles) {
var html = onRssFetched(err, articles);
callback(err, html);
});
},
sky: function (callback) {
feed(SKY_URL, function (err, articles) {
var html = onRssFetched(err, articles);
callback(err, html);
});
}
}, done);
function done(err, results) {
util.log('Received results: ' + Object.keys(results).join(','));
if (!err && results) {
var entry, html;
for (entry in results) {
html = results[entry];
res.write(html.join(''));
}
util.log('Send complete!');
res.end();
} else {
console.log(err || 'no data in results');
res.end('Unable to process your request');
}
}
}
function onRssFetched(err, articles) {
// limit number of articles;
articles = articles.slice(0, LIMIT);
var html = [];
if (err) {
html.push('<p>', UNABLE_TO_CONNECT = '</p>');
} else {
html.push('<ol>');
articles.forEach(function (entry) {
html.push('<li><a href="' + entry.link + '">' + entry.title + '</a></li>');
});
html.push('</ol>');
}
return html;
}
// -- Test Code ---------------------------------------------------------
if (require.main === module) {
(function () {
var req, res = {
writeHead: console.log,
write: console.log,
end: console.log
};
// onRequest(req, res);
})();
}
如果您遇到任何問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.