jQuery的deferred对象

deferred对象就是jQuery的回调函数解决方案。

它解决了如何处理耗时操作的问题,提供了更好的控制和javascript统一的编程接口。

ajax操作的链式写法

$.ajax('test.html')
    .done(function () {
        alert('success');
    })
    .fail(function () {
        alert('error');
    })

指定同一操作的多个回调函数

deferred允许自由添加多个回调函数。

$.ajax('test.html')
    .done(function () {
        alert('success');
    })
    .fail(function () {
        alert('error');
    })
    .done(function () {
        alert('第二个回调函数!')
    });

为多个操作指定回调函数

deferred对象允许为多个事件指定一个回调函数。

$.when($.ajax("test1.html"), $.ajax("test2.html"))
    .done(function () {
        alert("success")
    })
    .fail(function () {
        alert("fail")
    });

普通操作的回调函数接口

deferred对象把一套回调函数接口,从ajax操作扩展到所有操作。

$.when()的参数只能是deferred对象。

$.when($.ajax("test1.html"), $.ajax("test2.html"))
    .done(function () {
        alert("success")
    })
    .fail(function () {
        alert("fail")
    });

wait()函数返回的是deferred对象,可以加上链式操作。

$.when(wait(dtd))
    .done(function () {
        alert("success")
    })
    .fail(function () {
        alert("fail")
    });

wait()函数执行完毕,就会自动运行done()方法指定的回调函数。

deferred.resolve()方法和deferred.reject()方法

deferred对象有三种执行状态——未完成,已完成和已失败。

deferred.promise()方法

上面的dtd是一个全局对象,它的执行状态可以从外部改变。

var dtd = $.Deferred();// 新建一个deferred对象
var wait = function (dtd) {
    var tasks = function () {
        alert("执行完毕");
        dtd.resolve();// 改变deferred对象的执行状态
    };
    setTimeout(tasks, 2000);
    return dtd;
};

$.when(wait(dtd))
    .done(function () {
        alert("success")
    })
    .fail(function () {
        alert("fail")
    });
dtd.resolve();// 改变deferred对象的执行状态

在代码尾部加一行dtd.resolve(),改变dtd对象的执行状态,导致done()方法立即执行。

为了避免这种情况,jQuery提供了deferred.promise()方法。作用是在原来的deferred对象上返回另一个deferred对象,后者只开放与改变状态无关的方法(done()fail()),屏蔽与改变状态有关的方法(resolve()reject()),从而使得执行状态不能被改变。

var wait = function (dtd) {
    var dtd = $.Deferred();// 在函数内部,新建一个Deferred对象
    var tasks = function () {
        alert("执行完毕");
        dtd.resolve();// 改变deferred对象的执行状态
    };
    setTimeout(tasks, 5000);
    return dtd.promise();// 返回promise对象
};

$.when(wait())
    .done(function () {
        alert("success")
    })
    .fail(function () {
        alert("fail")
    });

另一种防止执行状态被外部改变的方法,使用deferred对象的构建函数$.Deferred()

$.Deferred()可以接受一个函数名作为参数,$.Deferred()所生成的deferred对象将作为这个函数的默认参数。

$.Deferred(wait);

除了上面两种方法之外,还可以直接在wait()对象上部署deferred接口。

dtd.promise(wait);

小结:deferred对象的方法

  1. $.Deferred() 生成一个deferred对象
  2. deferred.done() 指定操作成功时的回调函数
  3. deferred.fail() 指定操作失败时的回调函数
  4. deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用是在参数对象上部署deferred接口
  5. deferred.resolve() 手动改变deferred对象的运行状态为“已完成”,从而立即触发done()方法
  6. deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为”已失败”,从而立即触发fail()方法
  7. $.when() 为多个操作指定回调函数
  8. deferred.then() 可以把done()fail()合在一起写
$.when($.ajax("main.php"))
    .then(successFunc, failFunc);
  1. deferred.always()

用来指定回调函数,作用是不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。

$.ajax("test.html")
    .always(function () {
        alert("已执行")
    });