Ajax读jQuery之二十(Deferred对象)

Deferred对象是由 jQuery.Deferred 构造的,jQuery.Deferred
被达成为简单来说工厂格局

它用来消除JS中的异步编制程序,它服从 Common
Promise/A

规范。实现此规范的还有 when.js 和
dojo

 

$.Deferred作为新特征第②遍面世在本子1.5中,那些本子采取Deferred又完全重写了Ajax模块。

$.Deferred在jQuery代码自己四处被应用,分别是promise方法、DOM
ready
Ajax模块、动画模块。

这里以版本1.8.3剖析,由于1.7$.Callbacks从Deferred中抽离出来了,近期版本的deferred.js代码不过150行,而真的$.Deferred的贯彻唯有100行左右。

 

$.extend标示符$上挂了五个章程,如下

jQuery.extend({
    Deferred: function( func ) {
        var tuples = [
                // action, add listener, listener list, final state
                [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
                [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
                [ "notify", "progress", jQuery.Callbacks("memory") ]
            ],
        ...

        // All done!
        return deferred;
    },
    // Deferred helper
    when: function( subordinate /* , ..., subordinateN */ ) {
        var i = 0,
            resolveValues = core_slice.call( arguments ),
            length = resolveValues.length,
            ....

        return deferred.promise();
    }
});

 

$.Deferred的实现

  1. 创设八个$.Callbacks对象,分别表示成功,战败,处理中三种处境
  2. 创设了2个promise对象,具有state、always、then、primise方法
  3. 由此扩大primise对象生成最后的Deferred对象,再次来到该对象

 

$.when的实现

  1. 收受多少个目的,参数仅3个且非Deferred对象将随即实施回调函数
  2. Deferred对象和非Deferred对象混杂时,对于非Deferred对象remaining减1
  3. Deferred对象总数 = 内部营造的Deferred对象 +
    所传参数中蕴藏的Deferred对象
  4. 所传参数中有所Deferred对象每当resolve时remaining减1,直到为0时(全部都resolve)执行回调

 

那就是$.Deferred和$.when的全体了,各种艺术及选用稍后介绍。

代码阅读中会发现then和when方法的兑现最难精通,看多次,后感引人入胜,卓殊巧妙。then内部会利用不一致日常的递归,when用到了计数,每一回异步成功后减一,直到为0后代表一切异步操作成功,那时才可举办回调。

 

上面提到Deferred里有3个$.Callbacks的实例,Deferred本身则围绕那四个对象进行更高层次的肤浅。以下是Deferred对象的为主措施

  • done/fail/progress 是
    callbacks.add,将回调函数存入
  • resolve/reject/notify 是
    callbacks.fire,执行回调函数(或队列)

 

上面举一些演示看看哪些选择Deferred对象。

 

一、done/resolve

function cb() {
    alert('success')
}
var deferred = $.Deferred()
deferred.done(cb)
setTimeout(function() {
    deferred.resolve()
}, 3000)

在HTTP中象征后台重返成功景象(如200)时行使,即请求成功后可进行成功回调函数。

 

二、fail/reject

function cb() {
    alert('fail')
}
var deferred = $.Deferred()
deferred.fail(cb)
setTimeout(function() {
    deferred.reject()
}, 3000)

在HTTP中象征后台重返非成功景色时行使,即请求失利后可实施破产回调函数。

 

三、progress/notify

function cb() {
    alert('progress')
}
var deferred = $.Deferred()
deferred.progress(cb)
setInterval(function() {
    deferred.notify()
}, 2000)

在HTTP中象征请求进程中接纳,即请求进程中频频推行回调函数。那可用在文件上传时的loading百分比或进度条。

 

四 、链式操作

function fn1() {
    alert('success')
}
function fn2() {
    alert('fail')
}
function fn3() {
    alert('progress')
}
var deferred = $.Deferred()
deferred.done(fn1).fail(fn2).progress(fn3) // 链式操作
setTimeout(function() {
    deferred.resolve()
    //deferred.reject()
    //deferred.notify()
}, 3000)

如此那般能够很方便了拉长成功,失利,进程回调函数。

 

五,便利函数then,一回添加事业有成,战败,进程回调函数

function fn1() {
    alert('success')
}
function fn2() {
    alert('fail')
}
function fn3() {
    alert('progress')
}
var deferred = $.Deferred()
deferred.then(fn1, fn2, fn3)

调用then后还足以三番柒遍链式调用then添加八个例外回调函数,这么些then也多亏jQuery对 Common
Promise/A
的实现。

 

6、使用always方法为成功,战败状态添加同1个回调函数

var deferred = $.Deferred()
deferred.always(function() {
    var state = deferred.state() 
    if ( state === 'resolved') {
        alert('success')
    } else if (state === 'rejected') {
        alert('fail')
    }
})
setTimeout(function() {
    deferred.resolve()
    //deferred.reject()
}, 3000)

回调函数中得以选择deferred.state方法取得异步进度中的最后状态,那里小编调用的是deferred.resolve,因而最后的动静是resolved,表示成功。

 

七 、when方法保险四个异步操作全体得逞后才回调

function fn1() {
    alert('done1')
}
function fn2() {
    alert('done2')
}
function fn3() {
    alert('all done')
}

var deferred1 = $.Deferred()
var deferred2 = $.Deferred()

deferred1.done(fn1)
deferred2.done(fn2)
$.when(deferred1, deferred2).done(fn3)

setTimeout(function() {
    deferred1.resolve()
    deferred2.resolve()
}, 3000)

先后弹出了done① 、done二 、all done。
若是setTimeout中有3个reject了,fn3将不会被实施。

 

捌 、deferred.promise()方法重回只可以添加回调的对象,这几个指标与$.Deferred()重回的指标不相同,只可以done/fail/progress,无法resolve/reject/notify。即只好调用callbacks.add,没有callbacks.fire。它是正统Deferred对象的阉割版。

 

 

有了Deferred,大家运用jQuery书写ajax的风骨能够如此了

$.ajax(url)
 .done(success)
 .progress(handling)
 .fail(fail)

 

就如和原先相比也没怎么长处,但它还足以增进多个回调

$.ajax(url)
 .done(success1)
 .done(success2)
 .fail(fail2)
 .fail(fail2)

1.5事先的则不行

 

假如多个请求实现后才算成功,1.5事先的是无能为力消除的,现在则足以用$.when解决

var ajax1 = $.ajax(url1)
var ajax2 = $.ajax(url2)
$.when(ajax1, ajax2).done(success)

 

借使项目中有局地异步难点不妨用用Derferred。

 

相关:

http://jimliu.net/?p=64

http://www.infoq.com/cn/news/2011/09/js-promise

http://www.erichynds.com/jquery/using-deferreds-in-jquery/

http://sitr.us/2012/07/31/promise-pipelines-in-javascript.html

http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

 

相关文章