延迟对象,在jQuery的1.5引入,是经过调用jQuery.Deferred()方法建立一个可链式调用的工具对象。 它能够注册多个回调到回调队列, 调用回调队列,准备代替任何同步或异步函数的成功或失败状态。——jQuery API中文文档
简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是"延迟",因此deferred对象的含义就是"延迟"到将来某个点再执行。它解决了如何处理耗时操做的问题,对那些操做提供了更好的控制,以及统一的编程接口。——阮一峰
ajax 操做的链式写法php
$.ajax("test.html") .done(function(){ alert("success"); }) .fail(function(){ alert("error"); });
$.ajax()
操做完成后,若是使用的是低于1.5.0版本的jQuery,返回的是XHR对象,没法进行链式操做;若是是高于1.5.0版本,返回的是deferred对象,能够进行链式操做。能够看到,done()
至关于 success
方法,fail()
至关于 error
方法。采用链式写法之后,代码的可读性大大提升。css
这里着重强调一下 jqXHR 对象,从 jQuery 1.5 开始, $.ajax()
返回的 jqXHR对象 自己就是 deferred 对象,所以能够像上面代码中那样进行链式调用。html
从 jQuery 1.5 开始,$.ajax()返回的jqXHR对象 实现了 Promise 接口, 使它拥有了 Promise 的全部属性,方法和行为。(见Deferred object获取更多信息)。为了让回调函数的名字统一,便于在$.ajax()中使用。jqXHR也提供.error() .success()和.complete()方法。这些方法都带有一个参数,该参数是一个函数,此函数在 $.ajax()请求结束时被调用,而且这个函数接收的参数,与调用 $.ajax()函数时的参数是一致。这将容许你在一次请求时,对多个回调函数进行赋值,甚至容许你在请求已经完成后,对回调函数进行赋值(若是该请求已经完成,则回调函数会被马上调用)。
注意事项: jqXHR.success()
, jqXHR.error()
, 和 jqXHR.complete()
回调从 jQuery 1.8开始 被弃用过期,从jQuery 3.0开始被删除,你可使用 jqXHR.done()
, jqXHR.fail()
, 和 jqXHR.always()
代替。jquery
指定同一操做的多个回调函数
deferred 对象的一大好处,就是它容许你自由添加多个回调函数。仍是以上面的代码为例,若是ajax操做成功后,除了原来的回调函数,我还想再运行一个回调函数,怎么办?很简单,直接把它加在后面就好了。程序员
$.ajax("test.html") .done(function(){ alert('success'); }) .fail(function(){ alert('error'); }) .done(function(){ alert('第二个回调函数!'); });
回调函数能够添加任意多个,它们按照添加顺序执行。web
为多个操做指定回调函数
deferred 对象的另外一大好处,就是它容许你为多个事件指定一个回调函数,这是传统写法作不到的。ajax
请看下面的代码,它用到了一个新的方法 jQuery.when():编程
$.when($.ajax("test1.html"), $.ajax("test2.html")) .done(function(){ alert('success'); }) .fail(function(){ alert('error'); });
这段代码的意思是,先执行两个操做$.ajax("test1.html")和$.ajax("test2.html"),若是都成功了,就运行done()指定的回调函数;若是有一个失败或都失败了,就执行fail()指定的回调函数。api
$.when() 方法的使用具体 参见文档。promise
普通操做的回调函数接口
deferred 对象的最大优势,就是它把这一套回调函数接口,从ajax操做扩展到了全部操做。也就是说,任何一个操做----不论是ajax操做仍是本地操做,也不论是异步操做仍是同步操做----均可以使用deferred对象的各类方法,指定回调函数。
咱们来看一个具体的例子,为一个很耗时的操做 wait 指定回调函数:
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('error'); });
另外一种作法是直接将 wait 函数传入 $.Deferred()
:
$.Deferred(wait) .done(function(){ alert('success'); }) .fail(function(){ alert('error'); });
jQuery 规定,$.Deferred()
能够接受一个函数名(注意,是函数名)做为参数,$.Deferred()
所生成的 deferred 对象将做为这个函数的默认参数。
更具体的信息请参见 阮一峰的文档。
$.Deferred()
生成一个 deferred 对象。jQuery.Deferred( [beforeStart ] )
工厂函数建立一个新的deferred对象。
描述: 一个工厂函数,这个函数返回一个链式实用对象,用返回对象方法来在回调队列中注册多个回调, 调用回调队列,传递任何同步或异步函数的成功或失败状态。
beforeStart
: 类型 Function( Deferred deferred )
,一个构造函数返回以前调用的函数。
jQuery.Deferred
方法能够传递一个可选的函数, 这个函数在方法返回以前调用, 而且会把新的 deferred(延迟)对象做为 this 对象,将其做为第一个参数传递给函数。例如,被调用的函数可使用deferred.then()
绑定回调。
deferred.done()
指定操做成功时的回调函数。deferred.fail()
指定操做失败时的回调函数。deferred.promise()
没有参数时,返回一个新的 deferred。 对象,该对象的运行状态没法被改变;接受参数时,做用为在参数对象上部署 deferred 接口。deferred.resolve()
手动改变 deferred 对象的运行状态为"已完成",从而当即触发 done()
方法。
一个 Deferred(延迟)对象开始于 pending 状态。 任何回调使用deferred.then()
,deferred.always()
,deferred.done()
, 或者deferred.fail()
添加到这个对象都是排队等待执行。调用deferred.resolve()
转换 Deferred(递延)到 resolved(解决)的状态,并当即执行设置中任何的 doneCallbacks。调用deferred.reject()
转换 Deferred(递延)到 rejected(拒绝)的状态,并当即执行设置中任何的 failCallbacks。一旦对象已经进入了解决或拒绝状态,它处于该状态。回调仍然能够添加到解决或拒绝 Deferred(递延)- 他们会当即执行。
$.ajax()
返回的 jqXHR 对象 会根据请求返回的结果,自动改变自身的执行状态。可是,对于其余经过 $.Deferred()
方法生成的 deferred 对象,它们的执行状态必须由程序员手动指定,由代码决定在何时触发回调函数。
deferred.reject()
这个方法与 deferred.resolve()
正好相反,调用后将 deferred 对象的运行状态变为"已失败",从而当即触发 fail()
方法。$.when()
为多个操做指定回调函数。deferred.then()
方法
有时为了省事,能够把 done()
和 fail()
合在一块儿写,这就是 then()
方法。
$.when($.ajax( '/main.php' )) .then(successFunc, failureFunc);
若是 then()
有两个参数,那么第一个参数是 done()
方法的回调函数,第二个参数是 fail()
方法的回调方法。若是 then()
只有一个参数,那么等同于 done()
。
deferred.always()
方法
这个方法也是用来指定回调函数的,它的做用是,无论调用的是 deferred.resolve()
仍是 deferred.reject()
,最后老是执行。
$.ajax( 'test.html' ) .always( function() { alert('已执行!');} );
更多信息请参见 jQuery API中文文档。