最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

jqueryDeferred对象讲解

来源:动视网 责编:小采 时间:2020-11-27 20:32:26
文档

jqueryDeferred对象讲解

jqueryDeferred对象讲解:Deferred对象是由.Deferred构造的,.Deferred构造的,.Deferred被实现为简单工厂模式。 它用来解决JS中的异步编程,它遵循 Common Promise/A 规范。实现此规范的还有 when.js 和 dojo。 $.Deferred作为新特性首次出现在版本1.5中,这个版本
推荐度:
导读jqueryDeferred对象讲解:Deferred对象是由.Deferred构造的,.Deferred构造的,.Deferred被实现为简单工厂模式。 它用来解决JS中的异步编程,它遵循 Common Promise/A 规范。实现此规范的还有 when.js 和 dojo。 $.Deferred作为新特性首次出现在版本1.5中,这个版本


Deferred对象是由.Deferred构造的,.Deferred构造的,.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. 创建了一个promise对象,具有state、always、then、primise方法
  3. 通过扩展primise对象生成最终的Deferred对象,返回该对象

$.when的实现

  1. 接受若干个对象,参数仅一个且非Deferred对象将立即执行回调函数
  2. Deferred对象和非Deferred对象混杂时,对于非Deferred对象remaining减1
  3. Deferred对象总数 = 内部构建的Deferred对象 + 所传参数中包含的Deferred对象
  4. 所传参数中所有Deferred对象每当resolve时remaining减1,直到为0时(所有都resolve)执行回调

这就是.Deferred和.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 的实现。

    六、使用always方法为成功,失败状态添加同一个回调函数

    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)

    先后弹出了done1、done2、all done。 如果setTimeout中有一个reject了,fn3将不会被执行。

    八、deferred.promise()方法返回只能添加回调的对象,这个对象与$.Deferred()返回的对象不同,只能done/fail/progress,不能resolve/reject/notify。即只能调用callbacks.add,没有callbacks.fire。它是正统Deferred对象的阉割版。

    有了Deferred,我们使用jQuery书写ajax的风格可以这样了

    $.ajax(url)
     .done(success)
     .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

    文档

    jqueryDeferred对象讲解

    jqueryDeferred对象讲解:Deferred对象是由.Deferred构造的,.Deferred构造的,.Deferred被实现为简单工厂模式。 它用来解决JS中的异步编程,它遵循 Common Promise/A 规范。实现此规范的还有 when.js 和 dojo。 $.Deferred作为新特性首次出现在版本1.5中,这个版本
    推荐度:
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top