細かすぎて伝わらないjQuery拡張 (20) “$.series” – Advent Calendar 2016
この記事は賞味期限切れです。(更新から1年が経過しています)
$.series() は、連鎖的に直列処理を実行していく関数です。
$.series(callback, callback, …)
使い方
// 引数で渡した関数を順番に呼んでいきます
$.series(
function(){
console.log("Process: 1");
// 数値(ミリ秒)を返すとその時間分次の処理を遅延させます
return 1000;
},
function(){
console.log("Process: 2");
// 何も返さない(undefined)場合は `return 1;` と同じ
},
function(){
// Deferredオブジェクトを返すと処理完了時に次の処理に移行します
return $.ajax({url: "/api"}).done(function(){
console.log("Process: 3");
});
},
function(){
// false を返すとそこで処理を中断して reject します
return false;
}
)
.then(
function(){
console.log("--処理完了--");
},
function(){
console.log("--途中で処理が中断されました--");
}
);
渡した関数が返す値によって、次の処理までの挙動が変わります。
- 数値 : 数値(ミリ秒)待機してから次の処理へ
- Deferred : resolveされてから次の処理へ
- false : 一連の処理を中断してrejectする
- undefined : 何も返さない場合は 1 を返した場合と同じ
$.series() は Deferred を返すので、完了・失敗を then() 等で受け取る事ができます。
コード
$.series = function(){
var df = $.Deferred(),
args = arguments,
i = -1,
timer = null,
run;
run = function(){
var r;
clearTimeout(timer);
i += 1;
if(i >= args.length){
return df.resolve();
}
r = args[i]();
if(false === r){
df.reject();
}
r = (r === void 0) ? 1 : r;
switch($.type(r)){
case "number": timer = setTimeout(run, r); break;
case "object":
if($.isFunction(r.then)){
r.then(run ,function(){
df.reject();
});
}
break;
default: break;
}
}
run();
return df;
};
Cに必要なAとBをやって、Dに必要なCをやってからDやって…というような感じに連鎖的に直列処理したい時や、 タイムラインで組んだアニメーション等が作れそうですね。
普通に Deferred 等で繋いでいっても良いんですが、コードが見づらくなってしまうので、 気持ちよく書きたいがためにうまれた関数です。
コメント