jquery源码解析:jQuery延迟对象Deferred(工具方法)详解1
请先看上一课的回调对象。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的更多相关文章
- jquery源码解析:expando,holdReady,ready详解
jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的. jQuery.extend({ //当只有一个对象时,就把这个对象 ...
- jquery源码解析:addClass,toggleClass,hasClass详解
这一课,我们将继续讲解jQuery对元素属性操作的方法. 首先,我们先看一下这几个方法是如何使用的: $("#div1").addClass("box1 box2&quo ...
- jQuery 源码分析(十六) 事件系统模块 底层方法 详解
jQuery事件系统并没有将事件监听函数直接绑定到DOM元素上,而是基于数据缓存模块来管理监听函数的,事件模块代码有点多,我把它分为了三个部分:分底层方法.实例方法和便捷方法.ready事件来讲,好理 ...
- jQuery 源码解析(二十七) 样式操作模块 坐标详解
样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下坐标这一块. 对于坐标来说,jQuery提供了一个offset方法用于获取第一个匹配元素的坐标或者设置所有匹配元素的坐标,还有offse ...
- jQuery 源码解析(三十一) 动画模块 便捷动画详解
jquery在$.animate()这个接口上又封装了几个API,用于进行匹配元素的便捷动画,如下: $(selector).show(speed,easing,callback) ;如 ...
- Spring源码解析二:IOC容器初始化过程详解
IOC容器初始化分为三个步骤,分别是: 1.Resource定位,即BeanDefinition的资源定位. 2.BeanDefinition的载入 3.向IOC容器注册BeanDefinition ...
- tp6源码解析-第二天,ThinkPHP6编译模板流程详解,ThinkPHP6模板源码详解
TP6源码解析,ThinkPHP6模板编译流程详解 前言:刚开始写博客.如果觉得本篇文章对您有所帮助.点个赞再走也不迟 模板编译流程,大概是: 先获取到View类实例(依赖注入也好,通过助手函数也好) ...
- jQuery 源码分析(十五) 数据操作模块 val详解
jQuery的属性操作模块总共有4个部分,本篇说一下最后一个部分:val值的操作,也是属性操作里最简单的吧,只有一个API,如下: val(vlaue) ;获取匹配元素集合中第一个元素的 ...
- jQuery 源码分析(十三) 数据操作模块 DOM属性 详解
jQuery的属性操作模块总共有4个部分,本篇说一下第2个部分:DOM属性部分,用于修改DOM元素的属性的(属性和特性是不一样的,一般将property翻译为属性,attribute翻译为特性) DO ...
- LiteDB源码解析系列(2)数据库页详解
在这一篇里,我将用图文的方式展示LiteDB中页的结构及作用,内容都是原创,在描述的过程中有不准确的地方烦请指出. 1.LiteDB页的技术工作原理 LiteDB虽然是单个文件类型的数据库,但是数据库 ...
随机推荐
- mysql-5.6.24-win32解决没有my.ini并且修改编码
3.配置环境变量:新建一个系统变量: MYSQL_HOME, 值:D:\MySql\mysql5611 //这一步不做也行 4.修改MySql启动配置文件: 将安装目录下文件:my-default. ...
- Nginx源码完全注释(5)core/ngx_cpuinfo.c
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include ...
- K.O. ----- 配置文件没有提示
---------------siwuxie095 K.O. ----- 配置文件没有提示 1.解决方法一:联网 只要 PC 联网,配置文件中就有提示 2.解决方法二:手动导入约束文件 约束文件:hi ...
- 如何申请新浪SAE,发布自己的网站
你是否会看见诸如(***.sinaapp.com)类的域名?是否和新浪有什么关系?抑或想要一个免费的空间展示自己的个人主页;没问题,下面我来分享一下SAE的申请流程吧! 首先,打开SAE(http:/ ...
- Python 日期和时间戳的转换
Python 日期和时间戳的转换 1. Python中处理时间的模块 Python中处理时间的模块有time.datetime和calendar. 在Python中表示时间的方式: 时间戳:10位整数 ...
- CentOS7安装redis,并设置开机自启动
卸载redis 停止并删除所有已的rendis目录即可. rm -rf /home/wls/soft/redis-4.0.2 rm -rf /etc/redis* rm -rf /var/log/re ...
- Perl 学习笔记-子程序
1.定义子程序 使用sub关键字定义 ; 子程序名和标识符同要求, 但是有的特殊的可以用 &符号; 子程序是全局的, 不需要再使用前声明; 重名函数后者覆盖前者. sub roger{ ...
- 编写高质量代码改善C#程序的157个建议——建议149:使用表驱动法避免过长的if和switch分支
建议149:使用表驱动法避免过长的if和switch分支 随着代码变得复杂,我们很容易被过长的if和switch分支困扰. 一个类枚举类型Week如下: enum Week { Monday, Tue ...
- sqlplus 简单的几个查询语句
sqlplus 是用来和oracle进行交互的工具,可以在电脑端使用,也可以在服务器使用 常用命令 show 显示SQL Plus中的信息 connect 先无条件断 ...
- ComponentSpace SAML v2.0 for .NET 使用介绍
下载地址:http://samlsso.codeplex.com/ 以下描叙参考版本为其官网最新版本2.5.0.6.相对2.4版本,2.5有了很大改进,很多接口方法都变了.使用起来更方便,易懂. 广告 ...