jQueryのajaxでDeffered/Promiseを使う
jQuery ajaxの書き方
jQueryのajaxに関してよく見かけるサンプルはこうです。
1 2 3 4 5 6 7 8 9 |
$.ajax({ url: "ajax.html", success: function(data) { alert('success!!'); }, error: function(data) { alert('error!!!'); } }); |
ajax.htmlにアクセスして、ステータスコード200が返ってきたらsuccessのfuctionが実行され、それ以外のステータスコードの場合は、errorのfunctionが実行されます。
ただし、この記述は前回述べた死のピラミッドが形成されてしまいます。「ajaxでAの情報を取得した後にBの情報を取得する」という場合は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$.ajax({ url: "a.html", success: function(data) { $.ajax({ url: "b.html", success: function(data) { alert('success!!'); }, error: function(data) { alert('error!!!'); } }); }, error: function(data) { alert('error!!!'); } }); |
さらにさらに、「ajaxでAの情報を取得した後にBの情報を取得して、更にその後にCの情報を取得して・・・」となると・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$.ajax({ url: "a.html", success: function(data) { $.ajax({ url: "b.html", success: function(data) { $.ajax({ url: "c.html", success: function(data) { alert('success!!'); }, error: function(data) { alert('error!!!'); } }); }, error: function(data) { alert('error!!!'); } }); }, error: function(data) { alert('error!!!'); } }); |
死のピラミッドが形成されてきました。作った当時は良いけど、あとからこのコードを見直したり、別の人が保守作業をする場合に地獄を見ます。
jQuery.Deferredを使う
$.whenを使うとまとめる事ができます。ajaxで各情報を取得できた場合に.done()が実行されます。各ajaxの結果情報はhoge, fuga, piyoに格納されているので使えます。また.fail()メソッドをチェーンするとどれか1つでもajaxが失敗した場合fail()を実行します。
1 2 3 4 |
$.when($.ajax('a.html'), $.ajax('b.html'), $.ajax('c.html')) .done(function(hoge, fuga, piyo) { // do something }); |
ただし、この場合は並列な実行となるため「a.htmlで取得した情報をパラメータにしてb.htmlをajaxする」といった処理は記述できません。その場合は.thenでチェーンすると良さそうです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var hoge; var fuga; $.ajax("a.html") .then(function(_hoge) { hoge = _hoge; return $.ajax("b.html"); }) .then(function(_fuga) { fuga = _fuga; return $.ajax("c.html"); }) .then(function(piyo) { console.log(hoge + piyo + fuga); }); |
ajax()が成功した場合に.then()が実行されます。ajax(‘a.html’)の実行結果は_hogeに格納されているので_hogeの情報を使って更にajax()を実行しています。.thenでチェーンし続けることで、非同期で実行しつつ死のピラミッドが形成されていません。
最後に各変数の情報をconsole.logで表示していますが、最後にすべての情報を表示させようとすると_hoge, _fuga変数はスコープ外なので、変数を一度外に保存しておかないといけません。これはちょっと綺麗じゃないですね。