jQuery 源码分析笔记(3) Deferred机制


Posted in Javascript onJune 19, 2011

Deferred把回调函数注册到一个队列中,统一管理,并且可以同步或者异步地调用这些函数。
jQuery.Deferred()用来构造一个Deferred对象。该对象有状态值,共有三种: Rejected, Resolved和初始状态。其中Resolved表示该操作成功完成了,而Rejected 则表示出现了错误,调用失败。Deferred对象的主要成员如下:
done(callback): 注册一个callback函数,当状态为resolved时被调用。 * fail(callback): 注册一个callback函数,当状态为rejected时被调用。 * always(callback): 注册一个callback函数,无论是resolved或者rejected都会被调用。 * then(successCallback, failureCallback): 同时传入成功和失败的回调函数。 * pipe(successFilter, failureFilter): 在调用成功和失败的回调函数前先调用pipe 指定的函数。算是一种管道机制,拦截了函数调用。 * resolve(args): 把状态设置为Resolved。 * reject(args): 把状态设置为Rejected。 * promse(): 返回的是一个不完整的Deferred的接口,没有resolve和reject。即不能修改Deferred对象的状态。可以看作是一种只读视图。这是为了不让外部函数提早触发回调函数。比如$.ajax在1.5版本后不再返回XMLHttpRequest,而是返回一个封装了 XMLHttpRequest和Deferred对象接口的object。其中Deferred部分就是promise()得到的,这样不让外部函数调用resolve和reject,防止在ajax完成前触发回调函数。把这两个函数的调用权限保留给ajax内部。
这个模块的代码从939行开始,紧接着jQuery对象的声明。也算是一个基础核心代码了。同时也是1.5版本最大的变化之一。
实际上Resolve和Reject的代码逻辑是一样的,只是对应的状态不同而已。为了代码复用,内部先实现了一个Deferred,然后真正的Deferred内部new了两个Deferred,一个作为 Resolve,另一个作为Reject。
_Deferred对象内部维护了一个函数数组(callback list)。Done(f1, f2...)的工作就是把这些callback依次push到这个队列中保存下来。而resolveWith(带参的resolve)和resolve依次调用这写callback函数。
Done中,需要判断事件是否已经完成。如果callback加入chain时事件已经完成,则需要马上执行callback。这个特性是让callback不用再和触发异步事件声明写在一起的原因。比如原来必须写$.post("...", function(data) { ... })。这个success callback必须写在这里,而现在可以写:

var defer = $.post("..."); 
// ... 
defer.success(function(data) { 
// ... 
}); 
// ... 
defer.fail(function(data) { 
// ... 
});

这样异步事件的声明和回调函数就可以分别管理了。这是1.5版本重写后的最大变化。
pipe(successFilter, failureFilter)函数修改了原来对象中的callback list。在两个callback list前面用then函数分别插入了Filter函数。然后返回。这样当这个Deferred对象的状态变化时,会先调用pipe函数指定的Filter函数,然后才会调用callback list。
promise()则单纯许多,就是new一个新object,然后把需要的成员copy进去。这个需要的成员定义在一个叫promiseMethods常量中。
var promiseMethods = "done fail isResolved isRejected promise then always pipe".split(" ");
Javascript 相关文章推荐
EasyUI中的tree用法介绍
Nov 01 Javascript
jquery动态添加删除(tr/td)
Feb 09 Javascript
JavaScript合并两个数组并去除重复项的方法
Jun 13 Javascript
javascript实现继承的简单实例
Jul 26 Javascript
分享十三个最佳JavaScript数据网格库
Apr 07 Javascript
JS HTML图片显示Canvas 压缩功能
Jul 21 Javascript
SeaJS中use函数用法实例分析
Oct 10 Javascript
Vue使用vux-ui自定义表单验证遇到的问题及解决方法
May 10 Javascript
vue-cli 2.*中导入公共less文件的方法步骤
Nov 22 Javascript
vue模块拖拽实现示例代码
Mar 09 Javascript
Vue项目打包部署到iis服务器的配置方法
Oct 14 Javascript
vue select 获取value和lable操作
Aug 28 Javascript
jQuery 源码分析笔记(7) Queue
Jun 19 #Javascript
jQuery 源码分析笔记(5) jQuery.support
Jun 19 #Javascript
jQuery调用WebService的实现代码
Jun 19 #Javascript
非常棒的10款jQuery 幻灯片插件
Jun 14 #Javascript
在jquery中处理带有命名空间的XML数据
Jun 13 #Javascript
jquery 与NVelocity 产生冲突的解决方法
Jun 13 #Javascript
用Juery网页选项卡实现代码
Jun 13 #Javascript
You might like
PHP 日期时间函数的高级应用技巧
2009/10/10 PHP
php 大数据量及海量数据处理算法总结
2011/05/07 PHP
ajax php传递和接收变量实现思路及代码
2012/12/19 PHP
php时间戳转换的示例
2014/03/31 PHP
Codeigniter上传图片出现“You did not select a file to upload”错误解决办法
2014/06/12 PHP
php中的动态调用实例分析
2015/01/07 PHP
php数字运算验证码的实现代码
2015/07/30 PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
2020/02/16 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
2020/03/24 PHP
javascript中sort()的用法实例分析
2015/01/30 Javascript
全面解析JavaScript中apply和call以及bind(推荐)
2016/06/15 Javascript
jQuery模拟淘宝购物车功能
2017/02/27 Javascript
JS图片预加载插件详解
2017/06/21 Javascript
使用JS获取SessionStorage的值
2018/01/12 Javascript
node app 打包工具pkg的具体使用
2019/01/17 Javascript
webpack-url-loader 解决项目中图片打包路径问题
2019/02/15 Javascript
js+HTML5 canvas 实现简单的加载条(进度条)功能示例
2019/07/16 Javascript
通过实例了解Nodejs模块系统及require机制
2020/07/16 NodeJs
vue移动端写的拖拽功能示例代码
2020/09/09 Javascript
Python实现读取文件最后n行的方法
2017/02/23 Python
Python及Django框架生成二维码的方法分析
2018/01/31 Python
Django如何开发简单的查询接口详解
2019/05/17 Python
Django自定义用户表+自定义admin后台中的字段实例
2019/11/18 Python
Python hashlib模块实例使用详解
2019/12/24 Python
pytorch获取模型某一层参数名及参数值方式
2019/12/30 Python
Python操作Sqlite正确实现方法解析
2020/02/05 Python
马来西亚网上购物:Youbeli
2018/03/30 全球购物
Oracle性能调优原则
2012/05/03 面试题
毕业生实习鉴定
2013/12/11 职场文书
主题婚礼策划方案
2014/02/10 职场文书
怎样写好自我评价呢?
2014/02/16 职场文书
活动总结模板
2014/05/09 职场文书
关于安全的标语
2014/06/10 职场文书
党支部工作总结2015
2015/04/01 职场文书
外科护士长工作总结
2015/08/12 职场文书
导游词之秦始皇兵马俑博物馆
2019/09/29 职场文书