JavaScriptで非同期処理を行う場合に必須となるPromise。
ES2017ではasync/await構文により非同期処理が書きやすくなってきていますが、
それ以前ではPromiseのメソッドチェーンで頑張る必要があります。
少しずつ慣れてきたものの、ループが絡むと「どうやって書くんだっけ?」となるので、まとめてみます。
端的に言うとPromiseオブジェクトを配列につめてPromise.allする、という事になります。
Promiseのメソッドチェーンをasync/awaitで書き直してみました。
jQuery UIのダイアログを使用した際のPromiseを使用した書き方も書きました。
普通のPromise処理
非同期処理1回だけ実行する場合など、単純な場合はこれで良い。
2回以上続ける場合も.thenをつなげて行けばOK。
尚、チェーンの中で発生したエラーは.catchで拾える。
// asyncFuncは非同期処理。Promiseオブジェクトを返却する。 asyncFunc() .then(function(response) { /* asyncFuncからの戻り値を使用する処理 ・ ・ ・ */ }) .catch(function(error) { /* asyncFuncでエラーになった場合の処理 ・ ・ ・ */ });
Promiseをループ処理する場合
1個目のthen節でPromiseをループ処理している。
asyncFunc2から返されるPromiseオブジェクトをpromisesに格納していき、
Promise.allにpromisesを引数として渡す事で、forループが終了するまで後続処理の実行を待機する。
2個目のthen節でPromiseをループ処理した結果が引数で渡されるので、
1つずつ好きなように処理すればOK。
// asyncFunc1は非同期処理。Promiseオブジェクトを返却する。 asyncFunc1() .then(function(response) { const promises = []; // asyncFunc2を10回実行し、終了次第、次の処理へ。 for (var i=0; i<10; i++) { // asyncFunc2も非同期処理。Promiseオブジェクトを返却する。 // 返却されたPromiseオブジェクトはpromisesに格納されていく。 promises.push(asyncFunc2()); }; return Promise.all(promises); }) .then(function(response) { response.forEach(function(value) { /* asyncFunc2を10回実行した結果が配列で返されるので、 ループ等で取り出して使用する。 尚、配列内の順番は、実行した順になる。 ・ ・ ・ */ }); }) .catch(function(error) { /* asyncFuncでエラーになった場合の処理 ・ ・ ・ */ });
おわりに
1つでも resolve()、またはreject()された時に発火するPromise.race()もあるが、
効果的な使用場面が思い浮かばない・・・。
また、冒頭でも触れましたが、ES2017でasync/awaitが追加され、さらに簡潔に非同期処理が記載できるようになったとのこと。
こちらについてはまだ触れられていないので、勉強したら書きます。