请先看上一课的回调对象。Deferred是通过extend添加到jQuery中的工具方法。如下所示:

jQuery.extend({

  Deferred: function( func ) {

  },

  when: function( subordinate /* , ..., subordinateN */ ) {

  }
});

首先,来介绍下Deferred的使用:

var cb = $.Deferred();

setTimeout(function(){

  alert(1);

  cb.resolve();

},1000)

cb.done(function(){

  alert(2);

});

以上代码执行顺序:新建一个延迟对象cb -> setTimeout,一秒后执行方法弹出1 -> 执行cb.done方法,把弹出2的方法保存 ->一秒后,执行弹出1的方法,弹出1,然后调用cb.resolve(),只要调用了cb.resolve方法,就会执行弹出2的方法。

如果大家是按照我的课程来看的话,会发现它跟Callbacks非常相似。以上代码可以用Callbacks实现:

var cb = $.Callbacks();

setTimeout(function(){

  alert(1);

  cb.fire();

},1000)

cb.add(function(){

  alert(2);

});

从上可知:$.Callbacks()  <-> $.Deferred(),cb.fire()  <-> cb.resolve();,cb.add <-> cb.done。

延迟对象主要用来处理异步的情况,比如,以上场景,要先弹出1,再弹出2,。但由于弹出1需要异步操作(比如向后台Ajax请求数据),所以需要先把弹出2的方法保存起来,等Ajax请求结束后,弹出1后,再执行弹出2的方法。当然你也可以把弹出2的方法放在setTimeout的function里面,但是这样的话,在业务逻辑复杂情况下,这个function里面的代码会非常多,不易于扩展。因此,Deferred在Ajax中用的非常多。

Deferred拥有三套处理方法集合,上面的是第一套,它代表完成,成功,触发。

第二套是:代表未完成,失败,触发

$.Callbacks()  <-> $.Deferred(),cb.fire()  <-> cb.reject();,cb.add <-> cb.fail。

第三套是:进行时,触发

$.Callbacks()  <-> $.Deferred(),cb.fire()  <-> cb.notify();,cb.add <-> cb.progress。

Deferred在Ajax中的应用举例:

当我们正常使用ajax时,是使用下面的方法操作,ajax成功就调用success方法,失败,就调用error方法。

$.ajax({

  url:"xxx.php",

  success:function(){},

  error:function(){}

})

当你使用延迟对象来操作Ajax时,只需要:done代表成功,fail代表失败

$.ajax('xxx.php').done(function(){}).fail(function(){});

调用$.ajax时,返回的是一个Deferred对象。当ajax成功时,会调用resolve方法,当失败时会调用reject方法。

接下来,分析源码:

Deferred: function( func ) {
  var tuples = [
    [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],

    //once代表只执行一次,memory代表在fire调用之后的add添加的方法也会执行(默认不会执行)。之所有这样写,是因为成功和失败只需要触发一次,而进行中,可以一直触发。
    [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
    [ "notify", "progress", jQuery.Callbacks("memory") ]
  ],

  ...... 

  jQuery.each( tuples, function( i, tuple ) {  //对数组进行遍历,tuple就是数组中的每一项(也是一个数组)
    var list = tuple[ 2 ],     //jQuery.Callbacks(),返回一个回调对象
    stateString = tuple[ 3 ];    //"resolved","rejected",undefined

    promise[ tuple[1] ] = list.add;    //回调对象的add方法。

    //tuple[1] :"done","fail","progress",用来添加方法的。promise = {"done":list.add,"fail":list.add,"progress":list.add}

    if ( stateString ) {   //tuples数组的前两项进入if语句
      list.add(function() {
          state = stateString;

        }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
    }

    deferred[ tuple[0] ] = function() {   //deferred = {"resolve":function(){会调用deferred[resolveWith](),其实就是回调对象的fireWith方法},"reject":function(){以此类推},"notify":function(){以此类推}}
      deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
      return this;
    };
    deferred[ tuple[0] + "With" ] = list.fireWith;   //回调对象的fireWith方法,其实就是fire方法,因为fire方法就是调用fireWith进行操作的
  });

  ......

}

延迟对象之所有要使用回调方法的memory参数,是因为延迟对象需要用来处理保持状态的情形,举个例子:

var cb = $.Deferred();

setTimeout(function(){

  alert(1);

  cb.resolve();

},1000)

cb.done(function(){

  alert(2);

});

$("input").click(function(){      //点击之后,立刻弹出3

  cb.done(function(){

    alert(3);

  })

})

以上代码会先弹出1,然后弹出2。之后,就停止了。只有你点击input时,才会弹出3。因为延迟对象具有记忆功能,它使用的就是具有memory参数的回调对象。当点击input时,调用延迟对象的done方法,这个done方法会再次调用resolve方法,然后进行触发,弹出3。

加油!

jquery源码解析:jQuery延迟对象Deferred(工具方法)详解1的更多相关文章

  1. jquery源码解析:expando,holdReady,ready详解

    jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的. jQuery.extend({       //当只有一个对象时,就把这个对象 ...

  2. jquery源码解析:addClass,toggleClass,hasClass详解

    这一课,我们将继续讲解jQuery对元素属性操作的方法. 首先,我们先看一下这几个方法是如何使用的: $("#div1").addClass("box1 box2&quo ...

  3. jQuery 源码分析(十六) 事件系统模块 底层方法 详解

    jQuery事件系统并没有将事件监听函数直接绑定到DOM元素上,而是基于数据缓存模块来管理监听函数的,事件模块代码有点多,我把它分为了三个部分:分底层方法.实例方法和便捷方法.ready事件来讲,好理 ...

  4. jQuery 源码解析(二十七) 样式操作模块 坐标详解

    样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下坐标这一块. 对于坐标来说,jQuery提供了一个offset方法用于获取第一个匹配元素的坐标或者设置所有匹配元素的坐标,还有offse ...

  5. jQuery 源码解析(三十一) 动画模块 便捷动画详解

    jquery在$.animate()这个接口上又封装了几个API,用于进行匹配元素的便捷动画,如下: $(selector).show(speed,easing,callback)        ;如 ...

  6. Spring源码解析二:IOC容器初始化过程详解

    IOC容器初始化分为三个步骤,分别是: 1.Resource定位,即BeanDefinition的资源定位. 2.BeanDefinition的载入 3.向IOC容器注册BeanDefinition ...

  7. tp6源码解析-第二天,ThinkPHP6编译模板流程详解,ThinkPHP6模板源码详解

    TP6源码解析,ThinkPHP6模板编译流程详解 前言:刚开始写博客.如果觉得本篇文章对您有所帮助.点个赞再走也不迟 模板编译流程,大概是: 先获取到View类实例(依赖注入也好,通过助手函数也好) ...

  8. jQuery 源码分析(十五) 数据操作模块 val详解

    jQuery的属性操作模块总共有4个部分,本篇说一下最后一个部分:val值的操作,也是属性操作里最简单的吧,只有一个API,如下: val(vlaue)        ;获取匹配元素集合中第一个元素的 ...

  9. jQuery 源码分析(十三) 数据操作模块 DOM属性 详解

    jQuery的属性操作模块总共有4个部分,本篇说一下第2个部分:DOM属性部分,用于修改DOM元素的属性的(属性和特性是不一样的,一般将property翻译为属性,attribute翻译为特性) DO ...

  10. LiteDB源码解析系列(2)数据库页详解

    在这一篇里,我将用图文的方式展示LiteDB中页的结构及作用,内容都是原创,在描述的过程中有不准确的地方烦请指出. 1.LiteDB页的技术工作原理 LiteDB虽然是单个文件类型的数据库,但是数据库 ...

随机推荐

  1. Linux 安装elasticsearch、node.js、elasticsearch-head

    前提:下载es的安装包 官网可以下载 es官网 安装elasticsearch 1 新建两个文件夹 一个存放安装文件,一个存放解压后的文件 mkdir -p /export/software //存放 ...

  2. Miller-Rabin算法

    Miller-Rabin算法用于检测一个数n是否是素数.其时间复杂度上界为O(klog2(n)),其中k为检测的轮数.增大k可以提高Miller-Rabin算法的准确度. 要检测一个数是否为素数,简单 ...

  3. 对加密的了解(DES/3DES/AES区别 )

    DES 1977年1月,美国政府颁布:采纳IBM公司设计的方案作为非机密数据的正式. 目前在国内,随着三金工程尤其是金卡工程的启动,DES算法在POS.ATM.磁卡及智能卡(IC卡).加油站.高速公路 ...

  4. 技术串讲 CAS 有用

    CAS,全称为Compare and Swap,即比较-替换.假设有三个操作数:内存值V.旧的预期值A.要修改的值B,当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返回true,否则什么都不 ...

  5. Git回滚到历史节点(SourceTree篇)

    转自:http://blog.csdn.net/u010416101/article/details/78142697.https://www.zhihu.com/question/48178380 ...

  6. 回顾2017系列篇(三):UX设计大会,都预示了哪些设计趋势

    2017已接近尾声,在这一年中,无数的UX大会和设计大会在世界各地召开.每一场会议的召开,都是界内精英人士经验的交流和智慧的碰撞.虽然2017年的会议都已过去,但每场会议上的话题探讨,尤其是界内精英们 ...

  7. echo $[1 + 2] shell中 $[] 在bash中同$(()),用于算术计算

    shell脚本编写:echo $[ 11#8+1] 输出结果是几,为什么,怎么算来的?  摘自:https://zhidao.baidu.com/question/334766451.html   结 ...

  8. pageadmin去掉xxx

    首先,屏蔽网页标题栏上的版权信息. 这个版本的信息在Incs目录下,我添加代码的文件是web_top.ascx,在它的最底下加入下面的代码. <script language="jav ...

  9. HDU 6125 Free from square (状压DP+背包)

    题意:问你从 1 - n 至多选 m 个数使得他们的乘积不能整除完全平方数. 析:首先不能整除完全平方数,那么选的数肯定不能是完全平方数,然后选择的数也不能相同的质因子. 对于1-500有的质因子至多 ...

  10. 查看HDFS集群信息

    clusterID:集群ID,必须保持一致 1)在NameNode上查看 cat $HADOOP_HOME/dfs/name/current/VERSION #Fri Apr 18 11:56:57 ...