読者です 読者をやめる 読者になる 読者になる

JavaScriptでコールバック連結 (2)

JavaScript Programming

こんにちは、株式会社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.jsscheduling.htmlです。