** JavaScript では、実行結果を非同期で受け取る処理(ネットワーク越しの処理など)が多いと、コールバックが多発します。そこで、すっきり書くためのライブラリ「MyAsync.js」を自作しました。**
** jQuery.Deferred や Promise などより手軽に使えます。使い方は async.js と似てますが、ソースはもっとコンパクトなので、自由に改変して使って下さい。**
まずは MyAsync の使い方
■順次実行する MyAsync.run( )
複数の非同期処理を順番に実行します。
MyAsync.run(処理1,処理2,処理3,‥‥).end(最終処理);
HTML/JavaScript
<script src="MyAsync.js"></script>
<script>
MyAsync.run(
function(baton) {
// 処理1
proc_1(function(result) {
baton.next(result); // 次の処理へ
});
},
function(baton) {
// 処理1の結果
var result_1 = baton.result;
// 処理2
proc_2(function(result) {
baton.next(result); // 次の処理へ
});
},
function(baton) {
// 処理2の結果
var result_2 = baton.result;
// 処理3
proc_3(function(result) {
baton.next(result); // 次の処理へ → end()
});
}
).end(
function(baton) {
// 処理3の結果
var result_3 = baton.result;
// 最終処理などを記述
......
}
);
</script>
■一斉実行する MyAsync.all( )
複数の非同期処理を一斉に実行します。
MyAsync.all(処理1,処理2,処理3,‥‥).end(最終処理);
HTML/JavaScript
<script src="MyAsync.js"></script>
<script>
MyAsync.all(
function(baton) {
// 処理1
proc_1(function(result) {
baton.next(result); // 処理結果を登録
});
},
function(baton) {
// 処理2
proc_2(function(result) {
baton.next(result); // 処理結果を登録
});
},
function(baton) {
// 処理3
proc_3(function(result) {
baton.next(result); // 処理結果を登録
});
}
).end(
function(baton){
// 処理1~3の結果
var result_1 = baton.results[0];
var result_2 = baton.results[1];
var result_3 = baton.results[2];
// 最終処理などを記述
......
}
);
</script>
ざっくり解説
順次実行 MyAsync.run( ) について
-
run(...)
の引数に記述した順番で1つずつ実行されます - 各々の非同期処理を
function(baton){...}
でくるんで下さい -
baton.next()
で、各処理の完了を MyAsync に通知します -
baton.next(result)
で、処理結果を次の処理へ渡すこともできます -
baton.next(result, ms)
で、次の処理を ms ミリ秒遅延実行できます -
baton.result
で、直前の処理結果を取得できます -
baton.stop(result)
で、処理の中断もできます(end()
は実行されます)
一斉実行 MyAsync.all( ) について
-
all(...)
の引数に記述した処理を一斉に実行しますが、終了は順不同です - 各々の非同期処理を
function(baton){...}
でくるんで下さい -
baton.next(result)
で、各処理の完了を MyAsync に通知します - end処理では
baton.results
配列に全ての処理結果が格納されています - 終了順に関係なく
baton.results
配列には処理1の結果から格納されます
MyAsync.js
MyAsync.js
//------------------------------------------------
// MyAsyncモジュール
//------------------------------------------------
var MyAsync = (function() {
var self = {};
// 順次実行
self.run = function()
{
var run_funcs = arguments;
var run_index = -1;
var end_func = null;
var baton = {
index : -1,
result : "",
next : function(result, wait) {
if(result === undefined) result = "";
if(wait === undefined) wait = 0;
run_index++;
baton.index = run_index;
baton.result = result;
setTimeout(function(){
if(run_index < run_funcs.length) {
run_funcs[run_index](baton);
} else if(end_func) {
end_func(baton);
}
}, wait);
},
stop : function(result) {
if(end_func) {
baton.index = run_funcs.length;
baton.result = result;
baton.stopped = true;
baton.stop_index = run_index;
end_func(baton);
}
},
stopped : false,
stop_index : -1,
};
baton.next();
return {
end : function(callback){
end_func = callback;
}
};
};
// 一斉実行
self.all = function()
{
var all_funcs = arguments;
var all_results = [];
var cnt_done = 0;
var cnt_loop = 0;
var end_func = null;
(function loop(){
if(cnt_loop >= all_funcs.length)
return;
var baton = {
index : cnt_loop,
next : function(result) {
if(result === undefined) result = "";
all_results[this.index] = result;
cnt_done++;
// 全処理が終了
if(cnt_done == all_funcs.length){
if(end_func) {
baton.index = all_funcs.length;
baton.results = all_results;
end_func(baton);
}
}
},
stop : function(result) {
baton.next(result);
}
};
all_funcs[cnt_loop](baton);
cnt_loop++;
setTimeout(loop, 0);
})();
return {
end : function(callback){
end_func = callback;
}
};
};
return self;
})();
参考記事
・JavaScriptの非同期処理について
・JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる
・非同期処理ってどういうこと?JavaScriptで一から学ぶ
・JavaScriptのasync.jsでwaterfallとseries、parallelの違い
(・o・ゞ いじょー。