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.
いいえ、これは正しくありません。 2つのネストされた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個の非同期を実行できるように組み込み関数を備えた非同期ライブラリの1つを使用することです同時に機内での操作を可能にします。あなたのコードは有望なので、私は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
});
あなたのタイトルの提案とは異なり、この問題は「リクエスト - 約束」に起因するものではありません。この問題は、同時に複数のリクエストを処理しようとする2つのネストされたループによって発生します。 – jfriend00
いくつかの関連する回答:[nodejsアプリケーションから何百万もの並列httpリクエストを作成する方法?](http://stackoverflow.com/questions/38268371/how-to-make-millions-of-parallel-http-requests-from- nodejs-app/38272107#38272107)と[ノードjs。 "リクエスト"パッケージでいくつの同時リクエストを送信できますか?(http://stackoverflow.com/questions/36611890/in-node-js-how-many-simultaneous-requests-can-i-send-with-the -request-package/36612175#36612175)と[100万のリクエスト作成](http://stackoverflow.com/questions/34802539/node-js-socket-explanation/34802932#34802932)を参照してください。 – jfriend00
個人的には、Bluebirdの 'Promise.map()'の並行処理オプションを使用して、同時に何回のリクエストが飛行中であったかを管理することができます。 – jfriend00