Mach3.laBlog

細かすぎて伝わらないjQuery拡張 (20) “$.series” – Advent Calendar 2016

$.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 等で繋いでいっても良いんですが、コードが見づらくなってしまうので、 気持ちよく書きたいがためにうまれた関数です。

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


*