jQuery入門

トップ > jQuery > Deferred

Deferred

◆ $.Deferred() (1.5)

Deferred(延期された)オブジェクトは、未解決(pending)、解決(resolved)、棄却(rejected) のいずれかの状態を持つオブジェクトです。生成時は未解決(pending)の状態で、解決(resolved)または棄却(rejected)された時に何らかのアクションを起こしたい場合に利用されます。

var df = $.Deferred();                            // Deferredオブジェクトを生成する
df.done(function() { alert("Done!"); });          // 解決されたらDone!を表示する
df.fail(function() { alert("Fail!"); });          // 棄却されたらFail!を表示する
setTimeout(function() { df.resolve(); }, 3000);   // Deferredオブジェクトを3秒後に解決状態にする

done() や fail() も Deferredオブジェクトを返却するので、下記の様にも記述できます。

var df = $.Deferred();
df.done(function() { alert("Done!"); })
  .fail(function() { alert("Fail!"); });

$.get(), $.load(), $.ajax() などの Ajax関数が返却する jqXHRオブジェクトも、Deferredオブジェクトと同じように扱うことができます。

var df = $.get("xx2.htm");
df.done(function() { alert("Done!"); })
  .fail(function() { alert("Fail!"); });

$.when() を用いて、複数の非同期処理がすべて完了するのを待って、次のアクションを実行することが可能となります。

var df1 = $.get("xx.htm", function(data) {   // 非同期処理1(Ajax)
    $("#log").append("DF1\n");
});
var df2 = $.Deferred();                      // 非同期処理2(Animation)
$("#box").animate({ width:"100px", height:"100px" }, 3000, function() {
    $("#log").append("DF2\n");
    df2.resolve();
});
var df3 = $.Deferred();                      // 非同期処理3(Timeout)
setTimeout(function() {
    $("#log").append("DF3\n");
    df3.resolve();
}, 1000);
$.when(df1, df2, df3)   // 非同期処理1,2,3すべてが完了したら COMPLETE! を表示する
    .done(function() { $("#log").append("COMPLETE!\n"); })
    .fail(function() { $("#log").append("FAIL\n"); });
deferred.resolve([args]) (1.5)
deferred.resolveWith(context[, args]) (1.5)

Deferredオブジェクトを解決(resolved)状態にします。args には、done() や then() で指定するコールバック関数への引数を指定します。context には、コールバック関数で $(this) として参照されるコンテキストを指定します。

df.resolve(arg1, arg2, arg3);
deferred.reject([args]) (1.5)
deferred.rejectWith(context[, args]) (1.5)

Deferredオブジェクトを棄却(rejected)状態にします。args には、fail() や then() で指定するコールバック関数への引数を指定します。context には、コールバック関数で $(this) として参照されるコンテキストを指定します。

df.reject(arg1, arg2, arg3);
deferred.notify([args]) (1.5)
deferred.notifyWith(context[, args]) (1.5)

Deferredオブジェクトの状態を通知します。通知した際、Deferredオブジェクトの状態がまだ未解決(pending)の状態であれば、progress()で設定したコールバックが呼ばれます。

df.notify(arg1, arg2, arg3);
deferred.done(callback[, callback]) (1.5)
deferred.fail(callback[, callback]) (1.5)
deferred.progress(callback[, callback]) (1.5)
deferred.always(callback[, callback]) (1.5)

done()には Deferredオブジェクトが解決(resolved)状態になった時、fail() は棄却(rejected)状態になった時、progress() はオブジェクトが未解決(pending)の状態であるとnotify()によって通知された時、always() は解決(resolved)/棄却(rejected)いずれかの状態になった時に呼び出すコールバック関数を指定します。

var df = $.Deferred();
df.done(function()     { $("#log").append("Done!\n"); })
  .fail(function()     { $("#log").append("Fail!\n"); })
  .progress(function() { $("#log").append("Progress\n"); })
  .always(function()   { $("#log").append("Always\n"); });
deferred.then(doneCallback[, failCallback][, progressCallback]) (1.8)

done(), fail(), progress() のコールバックを一度に指定します。

var df = $.Deferred();
df.then(
    function() { $("#log").append("Done!\n"); },
    function() { $("#log").append("Fail!\n"); },
    function() { $("#log").append("Progress\n"); }
);
deferred.isResolved() (1.5)
deferred.isRejected() (1.5)

Deferredオブジェクトが解決(resolved)状態にあるか、棄却(rejected)状態にあるか確認します。

if (df.isResolved()) { ... }
if (df.isRejected()) { ... }
deferred.state() (1.5)

Deferredオブジェクトの状態を "pending", "resolved", "rejected" のいずれかで返します。

$("#log").append("status = " + df.state() + "\n");
deferred.promise([target]) (1.5)

Deferredオブジェクトを参照する Promiseオブジェクトを生成します。Promiseオブジェクトは Deferredオブジェクトとほぼ同様の動作をしますが、resolve(), resolveWith(), reject(), rejectWith(), notify(), notifyWith() メソッドを呼び出せない点のみが異なります。関数の戻り値に Deferredオブジェクトの代わりに Promiseオブジェクトを返すことで、Deferredオブジェクトの状態が外部から勝手に変更されないように隠蔽します。target を指定した場合、新規に Primiseオブジェクトを生成する代わりに、targetオブジェクトに Promiseオブジェクトの機能を付加します。

// キッチンタイマーを作成する
function KitchenTimer(sec) {
    this.timer = sec;
    this.intervalId = null;
    this.deferred = $.Deferred();

    // 100ms毎にカウントダウンする
    this.countdown = function() {
        this.timer -= 100;
        this.deferred.notify();   // 100ms毎に progress() のコールバックを呼び出す
        if (this.timer <= 0) {
            clearInterval(this.intervalId);
            this.deferred.resolve();  // 完了したら解決(resolved)状態にする
        }
    };

    // カウントダウンを開始する
    this.start = function() {
        this.intervalId = setInterval(this.countdown.bind(this), 100);
    };

    this.deferred.promise(this);
    return this;
}

var timer = new KitchenTimer(3000);
timer.done(function() { $("#log").append("Done!\n"); });
timer.progress(function() { $("#log").append("."); });
timer.start();
obj.promise([queueName][, target]) (1.6)

すべてのアクションが完了するのを監視するための Promiseオブジェクトを生成し、返します。queueName にはキュー名を指定します。省略するとアニメーション用のキュー fx が参照されます。

$("#d1").fadeOut(3000).fadeIn(3000);
$("#d1").promise().done(function() {
    alert("Complete!");
});
deferred.pipe([doneCallback][, failCallback]) (1.6-1.7)

then() と同様、完了時、エラー発生時のコールバック関数を指定しますが、jQuery 1.8 で廃止されました。代わりに then() を使用してください。

◆ $.when(deferreds) (1.5)

複数の Deferredオブジェクトを監視し、すべてが解決(resolved)状態になった場合に done() のコールバックを呼び出します。一つでも棄却状態になると fail() のコールバックを呼び出します。詳細は $.Deferred() を参照してください。

$.when(df1, df2, df3)   // 非同期処理1,2,3すべてが完了したら COMPLETE! を表示する
    .done(function() { $("#log").append("COMPLETE!\n"); })
    .fail(function() { $("#log").append("FAIL\n"); });

Copyright (C) 2013 杜甫々
初版:2013年2月3日
http://www.tohoho-web.com/js/jquery/deferred.htm