<目次>
(1) Ajaxでの繰り返し処理の順序性を保つ方法について
(1-1) JavaScriptやAjaxの処理順序について
(1-2) Ajax処理順序制御②:同一処理ループ時の順序性保持(処理B1⇒処理B2⇒処理B3・・)
(1-2-1) 問題のロジック
(1-2-2) 問題点の確認
(1-2-3) 解決するための構文
(1-2-4) 解決するためサンプルPG概要
(1-2-5) 解決するためサンプルPG
(1) Ajaxでの繰り返し処理の順序性を保つ方法について
JavaScriptでAjax(非同期処理)を習い始めの際に、処理が意図しない順番で起動した、という経験はないでしょうか?今回はそうしたAjaxの処理順序や、それらを狙った順番で実行するためのちょっとした技をご紹介いたします。
処理パターン毎に2回に分けてご紹介しており、今回のテーマは②の「同一処理をループ」する際に順序を保つ方法です。
(1-1) JavaScriptやAjaxの処理順序について
⇒「前回の記事」をご参照ください(処理の順序性が担保されない事、及びその解消法)
(1-2) Ajax処理順序制御②:同一処理ループ時の順序性保持(処理B1⇒処理B2⇒処理B3・・)
例えば、次のように「func_a⇒func_aが完了⇒func_b(1回目)⇒func_b(2回目)⇒・・・」といった順序で実行される処理があるとします。
(図121)

(1-2-1) 問題のロジック
(処理フロー)
function ProcessOrderCheck() {
/* 処理A */
var func_a = function(){
return [何らかの非同期処理]
}
/* 処理B(処理Aの結果を利用) */
$.when(func_a()).then(function(){
/* 繰り返しの非同期処理 */
do{
/* 何らかの非同期処理 */
$.get(
/* 中略 */
function(responseText) {
/* 中略 */
if(counter<[ループ回数]){
nextAjax(counter);
}
}
);
}while(counter<[ループ回数]);
});
}
(補足)
・「$.get(function(..){..});」はjQueryの非同期処理(Ajax)の記述です。
⇒(解説)jQueryのget()メソッドの使い方やパラメーターについて
・「$.when(..).then(..)」はjQueryの機能で処理順序を制御する記述です。詳しくは前回記事(下記URL)をご参照頂けたらと思います。
⇒(解説)JavaScriptやAjaxでの処理の順序性やその制御方法について
(1-2-2) 問題点の確認
一見すると特段問題ないようにも見えますが、しかし、この処理の問題点として処理B内の「do-while文の実行順序が保たれていない」という点があります。例えば、前回の記事の(1-2-3)でご紹介しているサンプルプログラムでは、大きな括りでの処理A⇒処理Bの順序性は「$.when()」のお陰で正しいですが、処理B内のdo-whileループで累乗計算した結果は順番通りになっていません・・
(1-2-3) 解決するための構文
上記の問題点と解消するため、元々do-while文で書いていた部分を、再帰呼び出し(末尾再帰)に書き換えます。
(Before)
/* 繰り返しの非同期処理 */
do{
/* 何らかの非同期処理 */
$.get(
/* 中略 */
function(responseText) {
/* 中略 */
}
);
}while(counter<[ループ回数]);
↓
(After)
/* 繰り返しの非同期処理 */
function nextAjax(i){
/* 何らかの非同期処理 */
$.get(
/* 中略 */
function(responseText) {
/* 中略 */
if(counter<[ループ回数]){
nextAjax(counter);
}
}
);
}
(図122)

(1-2-4) 解決するためサンプルPG概要
次に上記の構文を組み込んだサンプルプログラムの概要についてですが、処理内容は前回の記事の(1-2-2)と全く同じなので、そちらを参照頂けたらと思います。
(1-2-5) 解決するためサンプルPG
前回の「JavaScript(順序制御あり)」と殆ど一緒ですが、先ほどご紹介したdo-while⇒再帰呼び出し(末尾再帰)に変更した事により、繰り返し処理も正しい順序で行われるようになっています。
●JavaScript(順序制御あり+ループ順制御)
function ProcessOrderCheck2_v2() {
console.log("### 1: Process Start ! ");
/* 処理A */
var loop_num = 0;
var getLoopCount = function(){
return $.get('GetLoopCount'
,function(responseText) {
loop_num = responseText;
console.log("### 2: Get the loop num : "+loop_num);
});
}
/* 処理B(処理Aの結果を利用) */
$.when(getLoopCount()).then(function(){
var counter = 0;
var number = $('#num01').val();
var result = "BaseNum = "+number+"
LoopNum = "+loop_num+"
====
";
/* ■追記箇所 */
function nextAjax(i){
console.log("### 3: Get user given number : "+number+" pow: "+counter);
$.get('GetPowResult'
,{baseNum:number,powNumber:counter}
,function(responseText) {
result += responseText;
counter +=1;
$('#ajaxGetUserServletResponse').html(result);
console.log("### 4: Check value : "+counter);
/* ■追記箇所 */
if(counter<loop_num){
nextAjax(counter);
}
}
);
}
/* ■追記箇所 */
nextAjax(counter);
});
}