jQueryのdeferredで処理をthenで直列に繋げた時にうまく待機してくれなかった話
2015年08月25日 01時19分
久々にJavaScriptのソースとにらめっこする機会があった。
そこで気になったのが非同期処理の連結方法。
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 26 27 28 29 30 31 32 33 34 35 36 37 |
function func1() { var flag = getAsyncFuncStatus(); swtich (flag) { case 1: // 未完了時はリトライ setTimeout("func1()", 1000); break; case 2: // 完了時の処理 // ここで非同期処理が終わった処理を記述 doSomething(); // 次の非同期処理へ func2(); break; } } funciton func2() { var flag = getAsyncFuncStatus(); swtich (flag) { case 1: // 未完了時はリトライ setTimeout("func2()", 1000); break; case 2: // 完了時の処理 // ここで非同期処理が終わった処理を記述 doSomething(); // 次の非同期処理へ func3(); break; } } // func3も似たようなコードで記述 func1(); |
こんな感じで非同期処理が書かれていた。
非同期処理の完了部分に次の非同期処理の呼び出しが記述されていて見通しが悪く、
なんとかしたかったので検索してみたら速攻でdeferred, Promise辺りの単語にあたった。
既にjQueryを使っていたのでjQueryのdeferredを使ってみることにした。
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
function func1() { var dfd = $.Deferred(), proc = function() { var flag = getAsyncFuncStatus(); switch (flag) { case 1: setTimeout("proc()", 1000); break; case 2: // ここで非同期処理が終わった処理を記述 doSomething(); dfd.resolve(); break; } }; proc(); return dfd.promise(); } function func2() { var dfd = $.Deferred(), proc = function() { var flag = getAsyncFuncStatus(); switch (flag) { case 1: setTimeout("proc()", 1000); break; case 2: // ここで非同期処理が終わった処理を記述 doSomething(); dfd.resolve(); break; } }; proc(); return dfd.promise(); } // func3も似たようなコードで記述 func1() .then(func2()) .then(func3()); |
非同期処理の連結が外に出せて非常にスッキリした。
func1とfunc2の順番が逆になっても変更箇所は最後の呼び出し部分だけで済むし良い感じ。
とか思って実行してみたらfunc1の完了を待たずにfunc2とfunc3が実行されてしまう。
すっごい悩んで調べまくったらjQueryのバージョンが1.7でthenの挙動が1.8以上と違ったのが原因だった。
徒労感が半端ない理由で余計疲れた。
jQuery.Deferredを使うんだったら最低でも1.8以上にしないとネット上によく書かれているthenによる非同期処理の直列繋ぎはできないので要注意。