質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

2回答

6429閲覧

大量のPromiseを生成する時、並行処理される上限を設けたい

og24715

総合スコア832

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2017/05/22 12:18

タイトルの通り、http requestなどの処理をするPromiseを大量に生成する以下のようなコードで並行処理される上限を設けたいです。
以下のコードは、配列の要素数が少ないうちは期待した動作をしますが、要素数が多いとリクエスト先からエラーが返ります。
エラーの内容は失念しましたが、おそらく処理上限を超えたのでリクエストが破棄されたような動作をしました。

Pendingの状態にあるPromiseが上限を超えて追加されようとする時、一旦sleepで保留して、上限を下回り次第追加する方法を考えましたが、Promiseの状態を取得する方法、またPromiseがfulfilledになったときにsleepを解除する方法がわかりません。

上記の私が考えた方法以外にPromiseの処理上限を設ける方法がありましたら教えてください。

javascript

1const arrPromises = arrParams.map(param => new Promise((resolve, reject) => { 2 httpRequest(param) 3 .then(resolve) 4 .catch(reject); 5})); 6 7Promise 8 .all(arrPromises) 9 .then(console.log); 10 11

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

上限つけてみました。(たぶん動くはず)

JavaScript

1let myPromises = Array( 20 ).fill( 1 ).reduce( ( pre, curr, i )=> { 2 pre.push( new Promise( ( resolve, reject )=> { 3 let t = 1000 * ( Math.floor( Math.random() * 4 ) + 1 ); 4 setTimeout( resolve, t, i + ':' + t ); 5 } ) ); 6 return pre; 7}, [] ); 8let list = [], max = 3, cnt = 0; 9function runPromises() { 10 console.log( '!' ); 11 if ( !myPromises.length && !list.length ) { 12 // Finish! 13 console.log( 'Finish!' ); 14 } 15 while( myPromises.length && list.length < max ) { 16 let p = myPromises.shift(); 17 list.push( 0 ); 18 p.then( value => { 19 console.log( value ); 20 list.shift(); 21 runPromises(); 22 } ); 23 console.log( ++cnt ); 24 } 25} 26 27runPromises(); 28```**動くサンプル:**[https://jsfiddle.net/tL5vjw5h/](https://jsfiddle.net/tL5vjw5h/)

投稿2017/05/22 14:08

編集2017/05/22 14:15
kei344

総合スコア69400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

og24715

2017/05/23 02:16

なるほど。面白いです。 runPromisesが処理中のPromiseの数をlist配列で表していると思いますが配列である意味は何でしょう。 私なりに解釈して書き直してみました。 https://jsfiddle.net/0d2c81w8/2/
kei344

2017/05/23 02:21

とくにありません。何か考えながら書いていて見直ししていないので雑なところはあると思います。
guest

0

状況がよくわかりませんがrejectを拾ってしまうと
途中でとまってしまいませんか?
rejectの想定を404エラーなどだと想定しているのであれば
statusをみてresolveで処理してみてはいかがでしょうか?

sample

startが表示されてから1秒後に10秒間かけて1000個のデータを表示

javascript

1<script src="https://www.promisejs.org/polyfills/promise-6.1.0.min.js"></script> 2<script> 3var prm=[]; 4console.log("start"); 5for(var i=0;i<1000;i++){ 6 (function(i){ 7 prm[i]= new Promise(function(resolver){ 8 setTimeout(function(){console.log(i);resolver(this);},1000+10*i); 9 }); 10 })(i); 11} 12Promise.all( prm ).then(function(){ 13 console.log("end"); 14}); 15 16</script> 17

追記

なにか噛み合っていないようですね
私の理解力がないのでしょうか、お役に立てずに残念です
一応sample追加しときますが、おそらく質問者さんのやりたいこととは違うのでしょうね

<script src="https://www.promisejs.org/polyfills/promise-6.1.0.min.js"></script> <script> var prm=[]; console.log("start"); for(var i=0;i<100;i++){ (function(i){ prm[i]= new Promise(function(resolver){ var xhr = new XMLHttpRequest(); xhr.open('GET','recv.php?x='+i,true); xhr.addEventListener("load" ,function() { console.log(this.response) resolver(this); }); xhr.send(); }); })(i); } Promise.all( prm ).then(function(){ console.log("end"); }); </script>
  • 呼び出し先recv.php

PHP

1<?PHP 2sleep(3); 3print $_GET["x"]; 4?>

投稿2017/05/22 12:25

編集2017/05/22 14:12
yambejp

総合スコア114779

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

og24715

2017/05/22 12:58

reject はしてません。 状況がわからないと言われてもこれ以上の説明のしようがないんですがPromiseの配列を生成しているだけです。中身の処理はなんでもいいです。 上限を超えてPromiseを生成するときは処理中のPromiseが空くのを待ってPromiseを配列に追加したいだけです。 Stackoverflowに似た質問がありましたがもっとスマートな方法がないかと質問した次第です。 [javascript \- Node\.js API Request limit with request\-promise \- Stack Overflow](https://stackoverflow.com/questions/38048829/node-js-api-request-limit-with-request-promise)
yambejp

2017/05/22 13:20

なるほどNode.jsですね 普通のjavascriptのpromiseについては1000個発行しても 問題ないみたいですけどね
og24715

2017/05/22 13:43

node.jsでもブラウザーjsでも1000個生成すること自体は問題ないでしょう。 追記見ました。 何を意図としているのかforで配列にPromise突っ込んでるだけですよね。 これではprm配列のPending状態にある要素の上限を設定できてるとはいえませんよね。
yambejp

2017/05/22 14:14

すみませんPendingうんぬんのところで私の認識と違うようです お役に立てずに申し訳ないです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問