jQuery源码分析系列(31) : Ajax deferred实现
AJAX的底层实现都是浏览器提供的,所以任何基于api上面的框架或者库,都只是说对于功能的灵活与兼容维护性做出最优的扩展
ajax请求的流程:
1、通过 new XMLHttpRequest 或其它的形式(指IE)生成ajax的对象xhr。
2、通过xhr.open(type, url, async, username, password)的形式建立一个连接。
3、通过setRequestHeader设定xhr的请求头部(request header)。
4、通过send(data)请求服务器端的数据。
5、执行在xhr上注册的onreadystatechange回调处理返回数据。
这几步之中,
我们开发者可能会遇到的问题
1 跨域
2 json的格式
3 dataType
4 AJAX乱码问题
5 页面缓存
6 状态的跟踪
7 不同平台兼容
jquery主要就是解决上面这问题,之后就在这个基础之上进行扩展
jQuery2.0.3版的Ajax部分源码大概有1200多行,主要针对ajax的操作进行了一些扩展,使之更加灵活
jQuery在1.5中对AJAX模块的重写,增加了几个新的概念
AJAX模块提供了三个新的方法用于管理、扩展AJAX请求,分别是:
- 前置过滤器
那么在对包装器jqXHR对象做混入之前,我们要先准备好
1 异步队列deferred
2 回调队列Callbacks
// Deferreds deferred = jQuery.Deferred(), /** * 所有的回调队列,不管任何时候增加的回调保证只触发一次 * @type {[type]} */ completeDeferred = jQuery.Callbacks("once memory"),
给jqXHR扩充添加promise的属性和方法,然后添加complete方法,这里用的是回调列表的add方法(即添加回调)
deferred.promise(jqXHR).complete = completeDeferred.add;
此时的jqXHR就具有了promise的一些特性了与callback的回调列队了
当然这里有个重点,返回了一个只读的deferred对象
如果返回完整的deferred对象,那么外部程序就能随意的触发deferred对象的回调函数,很有可能在AJAX请求结束前就触发了回调函数(resolve),这就是与AJAX本身的逻辑相违背了。
所以为了避免不经意间改变任务的内部流程,我们应该只返回deferred的只读版本 deferred.promise()
然后把对应的done与fail改成别名success与error
jqXHR.success = jqXHR.done; jqXHR.error = jqXHR.fail;
我们还需要把用户自定的内部回调函数给注册到jqXHR对象上
// 增加回调队列 for (i in { success : 1, error : 1, complete : 1 }) { /** * 把参数的回调函数注册到内部jqXHR对象上,实现统一调用 * 给ajax对象注册 回调函数add * deferred返回complete,error外部捕获 */ jqXHR[i](s[i]); }
jqXHR.success(s.success) -> jqXHR.done -> jQuery.Callbacks(“once memory”)
jqXHR.error(s.error) -> jqXHR.fail -> jQuery.Callbacks(“once memory”)
jqXHR.complete(s.complete) -> jQuery.Callbacks(“once memory”).add(s.success)
待续….
您可能感兴趣的文章:
jQuery源码分析系列
jQuery源码分析系列(31) : Ajax deferred实现
在jQuery1.5中使用deferred对象 着放大镜看Promise
在jQuery 1.5中使用deferred对象的代码(翻译)
jQuery 源码分析笔记(3) Deferred机制
jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)
jQuery源码分析-05异步队列 Deferred 使用介绍
jQuery源码分析系列:Callback深入
浅析jQuery整体框架与实现(上)
jQuery 2.0.3 源码分析 Deferred概念