javascriptで複数の処理を異なる処理時間で直列に実行する方法

javascriptで複数の処理を異なる処理時間で直列に実行する

先日、javascriptで複数の処理を異なる時間で直列に処理する方法で手間取ったので、備忘録として投稿。

javascriptで移動→回転→点滅などのように複数のアニメーションをそれぞれ異なる時間で直列に実施する場合に以下の方法で対応したところ、問題なく動いた。
今回はfunc1の処理を500msかけて実行した後、func2の処理を1000msかけて処理し、その後func3の処理を100msかけて処理するコードをSampleとして書きました。

$(function(){
    //複数の処理(func1,func2,func3)を順番に指定された時間で実行する
    //0~500ms : func1を処理
    //501~1500ms : func2を処理
    //1501~1600ms : func3を処理
	func1({arg1_name:arg1_val , arg2_name:arg2_val , arg3_name:arg3_val , time:500})
		.then(func2.bind(null,{arg1_name:arg1_val , arg2_name:arg2_val , time:1000}))
		.then(func3.bind(null,{arg1_name:arg1_val , time:100}));
});

function func1(obj) {
    //処理成功時はresolve,失敗時はrejectを呼ぶ
	return new Promise(function (resolve, reject) {
		//func1で実行したい処理を記述(obj.arg1_nameでarg1_valを呼び出せる)
		setTimeout(function () {
			resolve();  //引数で渡した指定時間後にresolve()を呼び出し処理完了とする。
		}, obj.time);
	});
};

function func2(obj) {
	return new Promise(function (resolve, reject) {
		//func2で実行したい処理を記述
		setTimeout(function () {
			resolve();
		}, obj.time);
	});
};

function func3(obj) {
	return new Promise(function (resolve, reject) {
		//func3で実行したい処理を記述
		setTimeout(function () {
			resolve();
		}, obj.time);
	});
};

上記のコードの中身について、少しバラしながら詳細を見ていきます。

bindについて

bindはbindの対象となる関数に対して、引数の値で定義した新たな関数を生成します。第一引数に定義した値は対象となる関数内のthisの値として扱われます。今回の処理では各function内でthisは使用していないため、第一引数にはnullを定義しています。
func2の引数objには{}内の各プロパティで定義した値が渡されます。

$(function(){
	func1({arg1_name:arg1_val , arg2_name:arg2_val , arg3_name:arg3_val , time:500})
		.then(func2.bind(null,{arg1_name:arg1_val , arg2_name:arg2_val , time:1000}))
		.then(func3.bind(null,{arg1_name:arg1_val , time:100}));
});

function func2(obj) {
	return new Promise(function (resolve, reject) {
		//func2で実行したい処理を記述
		setTimeout(function () {
			resolve();
		}, obj.time);
	});
};

Promiseについて

まずpromiseは下記のようにpromiseオブジェクトを定義して使います。
promiseオブジェクトは処理成功時はresolve()を実行し、処理失敗時にはreject()を実行します。
また、delay部分に処理分の時間を設定することで、非同期処理時にdelayで設定した時間経過後に処理成功を表すresolve()を返すことができます。

new Promise(function(resolve, reject){
    //rejectについては処理が途中でコケた場合に投げる処理
    if(err){
        reject("errorcode");
    }

    //delayで指定した時間経過後に、処理完了のresolve()を実行する
    setTimeout(resolve(), delay);
});

thenについて

thenはPromiseオブジェクト内の関数が完了した際に、引数の中の処理が実行されます。
下の例では、処理成功時には100ms後にコンソールに「A」が表示され、
処理失敗時にはコンソールに「B」が表示されるようになっています。

function test(obj){ 
    return new Promise(function(resolve, reject){
    //途中でエラーが発生した場合はreject()を実行
    if(err){
        reject("errorcode");
    }

    //delayで指定した時間経過後に、処理完了のresolve()を実行する
    setTimeout(resolve(), 100);
});
}

test({name:hoge,code:hoge}).then(function(){
    console.log("A");
}).catch(function(){
    console.log("B");
});

また、thenについては複数のthenを繋げて記述することができるため、今回の処理のように複数の処理を異なる時間で順番に実行する場合は、下記のような記述になります。

func1({arg1_name:arg1_val , arg2_name:arg2_val , arg3_name:arg3_val , time:500})
		.then(func2.bind(null,{arg1_name:arg1_val , arg2_name:arg2_val , time:1000}))
		.then(func3.bind(null,{arg1_name:arg1_val , time:100}));