<目次>
(1) JavaScriptやAjaxでの処理の順序性やその制御方法について
(1-1) JavaScriptやAjaxの処理順序について
(1-2) Ajax処理順序制御①:異なる処理の順序性を保つ(処理A⇒処理B)
(1-2-1) 構文
(1-2-2) サンプルプログラム概要
(1-2-3) サンプルプログラム
(1-2-4) 実行順序の制御を行わないと、こんな感じです・・
(1-3) Ajax処理順序制御②:同一処理ループ時の順序性保持(処理B1⇒処理B2⇒処理B3・・)
(1) JavaScriptやAjaxでの処理の順序性やその制御方法について
JavaScriptでAjax(非同期処理)を習い始めの際に、処理が意図しない順番で起動した、という経験はないでしょうか?今回はそうしたAjaxの処理順序や、それらを狙った順番で実行するためのちょっとした技をご紹介いたします。
(1-1) JavaScriptやAjaxの処理順序について
JavaScriptやその非同期処理であるAjax(応答を待たずに操作継続できる=非同期)を利用する際には、処理の順序性が担保されていません。
下記の動画はその例です。JavaScriptで処理A⇒処理Bの順番で実行しますが、実際に結果がコンソールに出るのは処理B⇒処理Aの順番です。
(動画)プログラム上は1⇒2⇒3の順番で記述さているが、処理結果は1⇒3⇒2の順番でコンソール表示されている
なので「処理Aの完了を待ってから処理Bを始める」といった処理をするためには、工夫が必要になります。今回はAjaxの処理順序を保つ方法を、実例を使って2パターンご紹介します。
●異なる処理の順序性を保つ(処理A⇒処理B)
⇒上記の動画のような例(func_aとfunc_bは異なる処理)
⇒(1-2)でご紹介
●同一処理をループ時(forループなど)の順序性を保つ(処理B1⇒処理B2⇒処理B3⇒・・・)
⇒forループで同じ処理を行う場合でも開始した順番に終わるとは限らないため、その対処法について
⇒(1-3)でご紹介
(1-2) Ajax処理順序制御①:異なる処理の順序性を保つ(処理A⇒処理B)
例えば、次のようにfunc_a⇒func_bの順番で非同期処理を実行したいとします。
(図121)
(1-2-1) 構文
構文は次の「$.when」を使います。whenの中に完了を待つ関数を指定し、thenの中で完了後の後続処理を指定します。
(構文)
$.when([完了を待つ関数]).then(function(){[完了後の非同期処理]});
先ほどのfunc_a⇒func_bに適用すると、次のような骨組みになります。
function ProcessOrderCheck() { /* 非同期処理A */ var func_a = function(){ return [何らかの非同期処理] } /* 非同期処理B(非同期処理Aの結果を利用) */ $.when(func_a()).then(function(){ /* 非同期処理B */ }); }
次は、この構文を実際に使ったサンプルプログラムをご紹介します。
(1-2-2) サンプルプログラム概要
このプログラムでは、画面(JSP)のボタン押下でJavaScriptが呼び出され、その内部で更にServlet1(処理A)⇒Servlet2(処理B)と呼び出しています。
(図122)
処理Bは処理Aの結果(ループ回数)の分だけ繰り返し処理を行うため、処理Aの結果が出た後でないと、処理Bは正しく動かない作りです。
イメージしやすいように具体例を挙げてみます。
(具体例)累乗の計算
・JSP画面からある数「X」を入力してボタン押下⇒例では「5」
・処理A(ループ処理回数の取得=ランダムで5~10の数字nを取得)⇒例では「7」
・処理B(ループ処理=Xの0乗~Xのn乗までを計算)
次のサンプルプログラムでは、上記例で「$.when」を適用している様子が分かります。
(1-2-3) サンプルプログラム
■JavaScript(順序制御あり)
function ProcessOrderCheck2() { 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+"<br />LoopNum = "+loop_num+"<br />====<br />"; 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); }); }
●JavaScript(実行順序制御ありVersion)
(図112)
(動画123)
今回のテーマであるJavaScript以外のプログラム(JSP、Servlet)については、オーソドックスなものですので、こちらは画像のみのご紹介とさせて頂きます。
●JSP
入力された数字「number01」に対してJavaScriptの計算(ProcessOrderCheck)を実施
(図111)①
●Servlet1
ループ回数「random_val」を取得
(図111)③
●Servlet2
JavaScriptの各ループ内で呼び出すServletです(累乗の計算)
(図111)④
(1-2-4) 実行順序の制御を行わないと、こんな感じです・・
(参考動画124)
ご参考で、順序制御が無いバージョン(「$.when」の制御をしていない)の操作動画もご紹介します。こちらはループ回数を取得する前に累乗計算に入ってしまうため、1回しか計算が行われていません。
実際にコンソールのログの順序を見ても、1⇒3(累乗計算)⇒2(ループ回数取得)となっており、意図した処理になっていません。
●JavaScript(実行順序制御なしVersion)
(図111)②
(1-3) Ajax処理順序制御②:同一処理ループ時の順序性保持(処理B1⇒処理B2⇒処理B3・・)
上記の対応を行っても、依然としてforループ内の処理順序は不正なままです。こちらの修正については、下記の別記事でご紹介しています。