jQuery的回调管理机制(二)
jQuery.extend({
/*
* deferred对象的一大好处,就是它允许你自由添加多个回调函数。
* $.ajax("test.html")
.done(function(){ alert("哈哈,成功了!");} )
.fail(function(){ alert("出错啦!"); } )
.done(function(){ alert("第二个回调函数!");} );
*deferred对象的另一大好处,就是它允许你为多个事件指定一个回调函数,这是传统写法做不到的。
当两个操作都成功了才执行成功的回调函数,否则执行失败的回调函数
$.when($.ajax("test1.html"), $.ajax("test2.html"))
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
*deferred对象的最大优点,就是它把这一套回调函数接口,从ajax操作扩展到了所有操作。
也就是说,任何一个操作----不管是ajax操作还是本地操作,也不管是异步操作还是同步操作----
都可以使用deferred对象的各种方法,指定回调函数。
*deferred对象有三种执行状态----未完成,已完成和已失败。
*/
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") ]
],
state = "pending",
// 返回当前的执行状态
promise = {
state: function() {
return state;
},
// 不管执行状态是resolve还是reject,都执行回调。
always: function() {
// deferred是在该回调函数中定义的一个对象(后面),它将作为返回值被返回,大部分方法将被绑定在该对象中
deferred.done( arguments ).fail( arguments );
return this;
},
// 参数可传入三个函数,第一个是成功的回调,第二个是失败的回调,第三个。。呃。。
// 这个方法有些迷惑。。
then: function( /* fnDone, fnFail, fnProgress */ ) {
var fns = arguments;
// 递归调用jQuery.Deferred()方法,并传入func。这些func将被加入回调列表中
return jQuery.Deferred(function( newDefer ) {
jQuery.each( tuples, function( i, tuple ) {
var action = tuple[ 0 ],
//判断参数是不是函数,如果是就赋值给fn,第一参数对应done,第二个参数对应fail,。。。
fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
deferred[ tuple[1] ](function() {
//这里的this指,调用done、fail的对象,arguments指调用时传入的参数,比如函数。
var returned = fn && fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
}
});
});
fns = null;
}).promise();
},
// 提供一个方法将promise对象扩展到obj对象上。如果没有obj对象,则直接返回promise对象。
promise: function( obj ) {
return obj != null ? jQuery.extend( obj, promise ) : promise;
}
},
// 所有封装的方法都会绑定到该对象上返回
deferred = {};
//为了向后兼容,以前都是用promise.pipe?
promise.pipe = promise.then;
// 遍历之前定义的动作、监听、回调、最终状态组成的数组,进行初始化操作
jQuery.each( tuples, function( i, tuple ) {
// 取得数组当中的 jQuery.Callbacks("once memory"),并将执行结果赋值给list。
var list = tuple[ 2 ],
//取出数组中的表示最终状态的字符串 “resolved rejected”
stateString = tuple[ 3 ];
//将list,也就是jQuery.Callback()方法返回的self对象中的add方法,绑定到promise.resolve/reject/notify上
promise[ tuple[1] ] = list.add;
// 如果stateString有值,以为数组中的第三个小数组中是没有最终状态值的,所以需要if做判断
if ( stateString ) {
// 调用Callbask返回的对象中的add方法,向回调列表中增加三个回调方法:一个匿名函数(改变最终状态),一个disable,一个lock
list.add(function() {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
}
//将resolve()、reject()、notify()方法绑定到deferred对象上并暴露出来提供给用户调用
deferred[ tuple[0] ] = function() {
//调用deferred.resovleWith/rejectWith/notifyWith方法,这些方法是在下面定义的
deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
return this;
};
//将jQuery.Callback()方法返回的self对象中的fireWith方法绑定到deferred.resovleWith/rejectWith/notifyWith上
deferred[ tuple[0] + "With" ] = list.fireWith;
});
// 将promise对象所有的方法和属性扩展到deferred对象上,使之具有promise所具有的方法和属性,但promise中并不会包含一些不想暴露的方法,所以使用时,可以返回deferred.promise对象
promise.promise( deferred );
//如果有传入的func,则在deferred对象执行环境执行func,支持另外一种使用Deferred的方法。例如:$.Deferred( function(){} );
if ( func ) {
func.call( deferred, deferred );
}
// 返回deferred对象
return deferred;
},
//多个方法全都执行完毕后,执行回调函数
when: function( subordinate /* , ..., subordinateN */ ) {
......
}
});
jQuery的回调管理机制(二)的更多相关文章
- jQuery的回调管理机制(三)
jQuery.when()方法是jQuery内部使用回调机制的范例. // 参数为多个方法,这些方法全部执行完成之后执行回调 when: function( subordinate /* , ..., ...
- jQuery的回调管理机制
// 对option的一个缓存,避免每次都需要createOptions,option是创建Callback对象时的传入的参数// 每个option被存入optionsCache中类似于{memory ...
- Android包管理机制(二)PackageInstaller安装APK
前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...
- 你必须了解的java内存管理机制(二)-内存分配
前言 在上一篇文章中,我们花了较大的篇幅去介绍了JVM的运行时数据区,并且重点介绍了栈区的结构及作用,相关内容请猛戳!在本文中,我们将主要介绍对象的创建过程及在堆中的分配方式. 相关链接(注:文章讲解 ...
- x86保护模式 二 分段管理机制
分段管理机制 段选择子和偏移地址的二维虚拟地址转换为一维的线性地址 一 段定义和虚拟地址到线性地址的转换 三个参数定义段:段基地址 段界限 和段属性 同时也是段描述符的结构 段基地址为 ...
- Android的包管理机制浅析(二)
上篇刚好说到获取到了签名信息,以下进入安装过程,直接上源代码: private void installNewPackageLI(PackageParser.Package pkg, int pars ...
- 【python测试开发栈】—python内存管理机制(二)—垃圾回收
在上一篇文章中(python 内存管理机制-引用计数)中,我们介绍了python内存管理机制中的引用计数,python正是通过它来有效的管理内存.今天来介绍python的垃圾回收,其主要策略是引用计数 ...
- ARC内存管理机制详解
ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...
- 浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...
随机推荐
- IE9出现异常SCRIPT5011:不能执行已释放Script的代码
今天同事测试系统,突然出现一个异常SCRIPT5011:不能执行已释放Script的代码 应用场景:用模态方式打开个窗口,对于返回对象使用"=="与字符串比较时出现错误 我也用我的 ...
- Java常用类(二)String类详解
前言 在我们开发中经常会用到很多的常用的工具类,这里做一个总结.他们有很多的方法都是我们经常要用到的.所以我们一定要把它好好的掌握起来! 一.String简介 1.1.String(字符串常量)概述 ...
- IT规划,是否一定要梳理流程
IT规划,是面向企业业务的 IT战略规划,必然需要考虑业务的运营特点和需求.以往为企业提供IT规划咨询服务时,很多企业都提出,IT规划要满足业务的需求,那就要对业务足够熟 悉,而通过梳理流程能够达到这 ...
- linux环境变量的概述
https://blog.csdn.net/u010533843/article/details/54986646 https://www.linuxidc.com/Linux/2017-08/146 ...
- ./configure、make、make install 命令
https://www.cnblogs.com/tinywan/p/7230039.html https://www.sohu.com/a/191735643_505857 ./configure 该 ...
- javascript提取联通个人信息和通话记录的代码
由于一些巨大的困难,一些后端爬虫改成了前端爬虫. 前端爬虫是只有js语言,后端爬虫有python java nodejs php这些语言. 前端爬虫有window.document对象,在浏览器端的爬 ...
- C#中AppDomain.CurrentDomain.BaseDirectory与Application.StartupPath的区别
// 获取程序的基目录. System.AppDomain.CurrentDomain.BaseDirectory // 获取模块的完整路径. System.Diagnostics.Process.G ...
- Android播放器推荐:可以播放本地音乐、视频、在线播放音乐、视频、网络收音机等
下载链接:http://www.eoeandroid.com/forum.php?mod=attachment&aid=MTAxNTczfGMyNjNkMzFlfDEzNzY1MzkwNTR8 ...
- 5 -- Hibernate的基本用法 --1 ORM和Hibernate
目前流行的编程语言,如Java.C#等,它们都是面向对象的编程语言,而目前铸就的数据库产品,例如Oracle.DB2等,依然是关系数据库等.编程语言和底层数据库的发展不协调,催生出了ORM框架.ORM ...
- AcceptEx 以及 获取远程IP与port
// 獲取本地以及遠程的IP和port setsockopt(clientfd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&listenfd ...