From my understanding, wouldn't it only ever have up to user_words.length possible connections open at a time, since those are the requests that are being done while the Promise.all waits to resolve? I don't see how the connections are not being closed.
不,這是不正確的。您有兩個嵌套for
循環,因此您可以同時打開多達user_words.length
* how many subreddits there are
。請記住,rp()
和Promise.all()
不會阻塞,因此您需要運行嵌套的for
循環,以便在處理任何響應之前完成啓動每個單個連接。
它也看起來像你期望以某種方式同步返回結果的代碼行return top_subreddit
。你也做不到。你應該返回一個承諾,最終解決到期望的結果。
From my understanding, wouldn't it only ever have up to user_words.length possible connections open at a time, since those are the requests that are being done while the Promise.all waits to resolve? I don't see how the connections are not being closed.
這不是對Promise.all()
的正確理解。 Promise.all()
未被阻止。在代碼繼續退出之前,它不會「等待」,直到所有的承諾解決。它的行爲是異步的。您的代碼繼續執行您的for
循環的其他迭代,並且Promise.all()
在將來通過它的所有承諾完成時將其調用爲.then()
處理程序。您的for
循環的其他迭代繼續運行並堆積更多的套接字。
我認爲最簡單的方法是創建一個您想要處理的URL數組,然後使用其中一個已經具有內置函數的異步庫,以允許您運行最多N個異步同時在飛行中的操作。由於您的代碼是基於承諾的,因此我會選擇Bluebird的Promise.map()
來處理URL列表。
var Promise = require('bluebird');
function getBestSubreddit(messageText) {
var user_words = parse_message(messageText);
var top_subreddit = "";
var top_score = Number.MIN_SAFE_INTEGER;
return rp(dbUrl + '/.json?shallow=true').then(function(res) {
res = JSON.parse(res);
// build a list of URLs to process
var urls = [];
for (var subreddit in res) {
if (res.hasOwnProperty(subreddit)) {
for (var i = 0; i < user_words.length; i++) {
urls.push(dbUrl + '/' + subreddit + '/word_freqs/' + user_words[i] + '.json');
}
}
}
//
return Promise.map(urls, function(url) {
return rp(url);
}, {concurrency: 20}).then(function(allResults) {
// do any final processing of allResults here and return that value
// to become the resolved result of the returned promise
});
}
}
getBestSubreddit(someText).then(function(result) {
// process result here
}).catch(function(err) {
// handle error here
});
在本例中,我將併發請求的數量設置爲20。您可以嘗試將其更改爲更高還是更低的數字可以提高吞吐量。理想的數字取決於許多因素,包括您的本地執行環境,您請求的數據量,您擁有的帶寬以及您發出請求的目標主機以及它如何處理同時發生的請求。如果太快請求太多請求,您可能還需要關注目標的速率限制。
其他一些相關的答案:
How to make millions of parallel http requests from nodejs app?
In Node js. How many simultaneous requests can I send with the "request" package
Making a million requests
它仍然不是很清楚,我從你的問題到底是什麼導致你正在試圖獲得,但這是一個收集所有可能數據的版本。您最終會得到一個{result: result, subreddit: subreddit, word: word}
這種形式的對象,其中result
是您的rp()
對於給定的子分幣和給定單詞的結果。
var Promise = require('bluebird');
function getBestSubreddit(messageText) {
var user_words = parse_message(messageText);
var top_subreddit = "";
var top_score = Number.MIN_SAFE_INTEGER;
return rp(dbUrl + '/.json?shallow=true').then(function(res) {
res = JSON.parse(res);
// build a list of URLs to process
var requestData = [];
for (var subreddit in res) {
if (res.hasOwnProperty(subreddit)) {
for (var i = 0; i < user_words.length; i++) {
requestData.push({url:dbUrl + '/' + subreddit + '/word_freqs/' + user_words[i] + '.json', subreddit: subreddit, word: user_words[i]});
}
}
}
//
return Promise.map(requestData, function(url) {
return rp(requestData.url).then(function(result) {
return {result: result, subreddit: requestData.subreddit, word: requestData.word};
});
}, {concurrency: 20}).then(function(allResults) {
// now filter through all the data with appropriate subreddit
// allResults is an array of objects of this form {result: result, subreddit: subreddit, word: word}
// return whatever you want the final result to be after processing the allResults array
});
}
}
getBestSubreddit(someText).then(function(result) {
// process result here
}).catch(function(err) {
// handle error here
});
不像你的標題提出,問題不是由'request-promise'造成的。這個問題是由於你的兩個嵌套循環試圖並行執行大量請求而不是讓你的代碼控制同時有多少個正在運行的。 – jfriend00
一些相關的答案:[如何使從nodejs應用程序的數百萬並行http請求?](http://stackoverflow.com/questions/38268371/how-to-make-millions-of-parallel-http-requests-from- nodejs-app/38272107#38272107)和[在Node js中。我可以使用「請求」包發送多少個同步請求](http://stackoverflow.com/questions/36611890/in-node-js-how-many-simultaneous-requests-can-i-send-with-the -request-package/36612175#36612175)和[Making a million requests](http://stackoverflow.com/questions/34802539/node-js-socket-explanation/34802932#34802932)。 – jfriend00
就我個人而言,我可能會使用Bluebird的Promise.map()中的併發選項來管理同時有多少個請求正在運行。 – jfriend00