[解決済み] 非同期コールバック関数のセットを待機させるには?
質問
javascriptでこのようなコードを持っています。
forloop {
//async call, returns an array to its callback
}
これらの非同期呼び出しがすべて終わった後、私はすべての配列の最小値を計算したいです。
どのように私はそれらすべてのために待つことができますか?
今のところ唯一のアイデアは、doneというブール値の配列を持っていて、i番目のコールバック関数でdone[i]をtrueに設定し、while(not all are done) {}と言うことです。
edit: 1つの可能な、しかし醜い解決策は、各コールバックでdone配列を編集し、そして各コールバックから他のすべてのdoneが設定された場合にメソッドを呼び出し、したがって完了する最後のコールバックは、継続するメソッドを呼び出すことだと思います。
事前にありがとうございます。
どのように解決するのですか?
コードがあまり具体的でないので、シナリオを作ってみます。 例えば、10回のajax呼び出しがあり、その10回のajax呼び出しの結果を蓄積し、それらがすべて完了したときに何かを行いたいとします。 このように、データを配列に蓄積して、最後の1つが終了したときに追跡することで実現できます。
手動カウンター
var ajaxCallsRemaining = 10;
var returnedData = [];
for (var i = 0; i < 10; i++) {
doAjax(whatever, function(response) {
// success handler from the ajax call
// save response
returnedData.push(response);
// see if we're done with the last ajax call
--ajaxCallsRemaining;
if (ajaxCallsRemaining <= 0) {
// all data is here now
// look through the returnedData and do whatever processing
// you want on it right here
}
});
}
注意: エラー処理はここで重要です (ajax呼び出しをどのように行うかによって異なるため、表示されません)。 1つのajaxコールが完了しない場合、エラーになるか、長い時間スタックするか、長い時間後にタイムアウトする場合に、どのように対処するかを考えておきたいと思うことでしょう。
jQuery プロミス
2014年の回答への追記です。 最近は、この手の問題を解決するためにプロミスがよく使われるようになりましたので、jQueryの
$.ajax()
はすでにプロミスを返しており
$.when()
は約束のグループがすべて解決されたときに知らせてくれ、あなたのために返り値を集めてくれます。
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push($.ajax(...));
}
$.when.apply($, promises).then(function() {
// returned data is in arguments[0][0], arguments[1][0], ... arguments[9][0]
// you can process it here
}, function() {
// error occurred
});
ES6標準プロミス
kbaの回答で指定されているように : ネイティブプロミスが組み込まれている環境(モダンブラウザやnode.js、babeljs transpileの使用やプロミスポリフィルの使用)であれば、ES6仕様のプロミスを使用することができます。 参照 この表 を参照してください。 プロミスはIEを除く、現在のほぼすべてのブラウザでサポートされています。
もし
doAjax()
がプロミスを返すなら、こうすればいい。
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(doAjax(...));
}
Promise.all(promises).then(function() {
// returned data is in arguments[0], arguments[1], ... arguments[n]
// you can process it here
}, function(err) {
// error occurred
});
プロミスでない非同期処理をプロミスを返す処理にする必要がある場合、以下のように"promisify"することが可能です。
function doAjax(...) {
return new Promise(function(resolve, reject) {
someAsyncOperation(..., function(err, result) {
if (err) return reject(err);
resolve(result);
});
});
}
そして、上のパターンで
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(doAjax(...));
}
Promise.all(promises).then(function() {
// returned data is in arguments[0], arguments[1], ... arguments[n]
// you can process it here
}, function(err) {
// error occurred
});
ブルーバード・プロミス
より機能豊富なライブラリ、例えば ブルーバードプロミスライブラリ のような機能豊富なライブラリを使用する場合、これを容易にするためにいくつかの追加機能が組み込まれています。
var doAjax = Promise.promisify(someAsync);
var someData = [...]
Promise.map(someData, doAjax).then(function(results) {
// all ajax results here
}, function(err) {
// some error here
});
関連
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] JavaScriptのオブジェクトが空であることをテストするにはどうすればよいですか?
-
[解決済み] JavaScriptで空文字列/未定義文字列/null文字列をチェックするにはどうすればよいですか?
-
[解決済み] JavaScriptで要素のクラスを変更するにはどうすればよいですか?
-
[解決済み] JavaScriptで文字列をbooleanに変換するにはどうしたらいいですか?
-
[解決済み] どうすればjQueryに非同期ではなく、同期のAjaxリクエストを実行させることができますか?
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] bootstrap のポップオーバーがすべての要素の上に表示されない
-
[解決済み] javascript includes() 大文字小文字を区別しない
-
[解決済み] JavaScriptの文字列プリミティブとStringオブジェクトの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] AngularJSのエラーです。Cross Origin リクエストはプロトコルスキーム http, data, chrome-extension, https に対してのみサポートされています。
-
[解決済み] URL/アドレスバーからJavascriptの関数を呼び出す
-
[解決済み] 文字列が空白であるかどうかをチェックする
-
[解決済み] React js 親コンポーネントから子コンポーネントの状態を変更する
-
[解決済み] 文字列がhtmlであるかどうかをチェックする
-
[解決済み] JavaScriptでの大文字小文字を区別しない正規表現
-
[解決済み] $.ajax実行中にローディングイメージを表示する
-
[解決済み] jQueryを使用して、すべてのクリックイベントハンドラを削除するにはどうすればよいですか?
-
[解決済み] javascriptのキャンバスで画像をリサイズする (スムーズ)
-
[解決済み] V8 Javascript エンジンのスタンドアロン実行