JavaScriptでコールバック連結 (2)
こんにちは、株式会社CFlatです。
一週挟みましたが、「JavaScriptでコールバック連結」の続きです。
それでは前回の処理の流れを、もう一度見ていきます。
(1) ボタンを表示するためのアニメーションを実行する
(2) スロットアニメーションを読み込む
(3) (1)の完了後、ボタンが押されるのを待つ
(4) (3)が完了したら、サーバー上のAPIに、当たるか外れるかの結果を問い合わせる
(5) (3)が完了して(2)が未完了であれば、ローディング表示を行う
(6) (3)と(2)が完了したら、もしローディング表示があれば消し、スロットアニメーションを表示する
(7) (4)が完了したら、結果に応じたアニメーションを読み込む
(8) (6)が完了して(7)が未完了であれば、ローディング表示を行う
(9) (6)と(7)が完了したら、もしローディング表示があれば消し、結果アニメーションを表示する
(10) (9)が完了したら、特定のページに遷移する
これを一般化した書き方にすると、このようになります:
・非同期処理(1)を開始
・非同期処理(2)を開始
・非同期処理(1)の完了時、非同期処理(3)を開始
・非同期処理(3)の完了時、非同期処理(4)を開始
・非同期処理(3)が完了、かつ非同期処理(2)が未完了の際、処理(5)を実行
・非同期処理(2)(3)が共に完了時、非同期処理(6)を開始
・非同期処理(4)の完了時、非同期処理(7)を開始
・非同期処理(6)が完了、かつ非同期処理(7)が未完了の際、処理(8)を実行
・非同期処理(6)(7)が共に完了時、非同期処理(9)を開始
・非同期処理(9)の完了時、処理(10)を実行
どうも、ほとんどが同じことを示しているようですので、必要な機能を抽出してみます。
・ある処理を開始済みかどうか、終了済みかどうかを確認する
・0個以上の処理が全て完了するのを待って、次の処理を実行する
・処理のスケジューリングは、動的に行えなければならない
これらをコードに直すと、各非同期処理の失敗時の処理を除けば、こんな感じにするとよさそうです。
var scheduler = new Scheduler() ; scheduler.wait([], {1: async_1, 2: async_2}) .wait([1], {3:async_3}) .wait([3], function(schedule) { if (!schedule.scheduler.isFinished(2)) schedule.scheduler.wait([], {5: func_5}); }) .wait([2, 3], function(schedule) { if (schedule.scheduler.isTriggered(5)) func_6a(); schedule.scheduler.wait([], {6: async_6}); }) ……
上記の部分までを実際に組んでみたら、こうなりました。
(async3までの方が時間がかかる場合) scheduling_test async_1() started async_2() started async_1() finished async_3() started async_2() finished async_3() finished async_6() started async_6() finished (async2までの方が時間がかかる場合) scheduling_test async_1() started async_2() started async_1() finished async_3() started async_3() finished func5() started async_2() finished func6a() started async_6() started async_6() finished
ソースはscheduler.jsとscheduling.htmlです。