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请求,分别是:
- 前置过滤器 jQuery. ajaxPrefilter
- 请求分发器 jQuery. ajaxTransport,
- 类型转换器 ajaxConvert
除此之后还重写了整个异步队列处理,加入了deferred,可以将任务完成的处理方式与任务本身解耦合,使用deferreds对象,多个回调函数可以被绑定在任务完成时执行,甚至可以在任务完成后绑定这些回调函数。这些任务可以是异步的,也可以是同步的。
比如
1.链式反馈done与fail
$.ajax({
url: "script.php",
type: "POST",
data: {
id: menuId
},
dataType: "html"
}).done(function(msg) {
$("#log").html(msg);
}).fail(function(jqXHR, textStatus) {
alert("Request failed: " + textStatus);
});
2.分离异步与同步处理
var aajax = $.ajax({
url: "script.php",
type: "POST",
data: {
id: menuId
},
dataType: "html"
}).fail(function(jqXHR, textStatus) {
alert("Request failed: " + textStatus);
});
//同步还在执行代码,这个函数有可能在AJAX结束前调用
dosomething()
//异步还在等在成功响应
aajax.done(function(msg) {
$("#log").html(msg);
})
不再被限制到只有一个成功,失败或者完成的回调函数了。相反这些随时被添加的回调函数被放置在一个先进先出的队列中。
3.同时执行多个ajax请求
function ajax1() {
return $.get('1.htm');
}
function ajax2() {
return $.get('2.htm');
}
$.when(ajax1(), ajax2())
.then(function() {
//成功
})
.fail(function() {
//失败
});
这个比较复杂一点,原理其实就是$.get返回的是一个deferred对象,每个jQuery的AJAX方法返回值都包含一个promise函数,用来跟踪异步请求。Promise函数的返回值是deferred对象的一个只读视图
Deferreds通过检测对象中是否存在promise()函数来判断当前对象是否可观察。$.when()会等待所有的AJAX请求结束,然后调用通过 .then(), .fail()注册的回调函数(具体调用哪些回调函数取决于任务的结束状态)。这些回调函数会按照他们的注册顺序执行
显而易见,deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口
jqXHR 对象
说白了无非就是在ajax的实现逻辑中,把deferred对象给掺进去了,使之整个ajax方法变成了一个deferred对象
在ajax方法中返回的是jqXHR一个包装对象,在这个对象里面混入了所有实现方法
ajax: function(url, options) {
//.........
return jqXHR
}
从jQuery 1.5开始,$.ajax() 返回XMLHttpRequest(jqXHR)对象,该对象是浏览器的原生的XMLHttpRequest对象的一个超集。例如,它包含responseText和responseXML属性,以及一个getResponseHeader()方法。当传输机制不是是XMLHttpRequest时(例如,一个JSONP请求脚本,返回一个脚本 tag 时),jqXHR对象尽可能的模拟原生的XHR功能。
从jQuery 1.5.1开始, jqXHR对象还包含了overrideMimeType方法 (它在jQuery 1.4.x中是有效的,但是在jQuery 1.5中暂时的被移除)。.overrideMimeType() 方法可能用在beforeSend()的回调函数中,例如,修改响应的Content-Type信息头:
为了让回调函数的名字统一,便于在$.ajax()中使用。jqXHR也提供.error() .success()和.complete()方法。这些方法都带有一个参数,该参数是一个函数,此函数在 $.ajax()请求结束时被调用,并且这个函数接收的参数,与调用 $.ajax()函数时的参数是一致。这将允许你在一次请求时,对多个回调函数进行赋值,甚至允许你在请求已经完成后,对回调函数进行赋值(如果该请求已经完成,则回调函数会被立刻调用)。
为了向后兼容XMLHttpRequest ,一jqXHR对象将公开下列属性和方法:
readyStatestatusstatusTextresponseXMLand/orresponseText当底层的请求分别作出XML和/或文本响应setRequestHeader(name, value)从标准出发,通过替换旧的值为新的值,而不是替换的新值到旧值getAllResponseHeaders()getResponseHeader()abort()

那么在对包装器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源码分析系列(31) : Ajax deferred实现的更多相关文章
- jQuery源码分析系列(36) : Ajax - 类型转化器
什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...
- jQuery源码分析系列(37) : Ajax 总结
综合前面的分析,我们总结如下3大块: jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求 前置过滤器 jQuery. ajaxPrefilter 请求分发器 jQuery ...
- jQuery源码分析系列(33) : AJAX中的前置过滤器和请求分发器
jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求,分别是: 1.前置过滤器 jQuery. ajaxPrefilter 2.请求分发器 jQuery. ajaxTran ...
- jQuery源码分析系列(30) : Ajax 整体结构
开头引用一段 想起一句话:前端研究,研究个屁~ 的确如此呀.补充下联:前端设计,设计个屁~ 前端目前最大的困境是,如 HTML 一样,无论你承不承认,市场上并不太需要 HTML 高手 其实这里引发一个 ...
- jQuery源码分析系列(34) : Ajax - 预处理jsonp
上一章大概讲了前置过滤器和请求分发器的作用,这一章主要是具体分析每种对应的处理方式 $.ajax()调用不同类型的响应,被传递到成功处理函数之前,会经过不同种类的预处理(prefilters). 预处 ...
- jQuery源码分析系列(35) : Ajax - jsonp的实现与原理
ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本 json核心就是:允许用户传递一个callba ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
随机推荐
- 织梦cms更新新建的栏目提示:DedeTag Engine Create File False:C:/phpStudy/WWW/
这个问题怎么解决呢?只是更换了一下栏目名称.增加了新的栏目,结果就不行了. 问题原因: 新建的栏目没有"列表命名规则",导致cms解析的时候,出现解析错误. 解决办法 在下图填入: ...
- Git小记
Git简~介 Git是一个分布式版本控制系统,其他的版本控制系统我只用过SVN,但用的时间不长.大家都知道,分布式的好处多多,而且分布式已经包含了集中式的几乎所有功能.Linus创造Git的传奇经历就 ...
- linux系统目录结构与层级命令使用
笔者使用的是ubuntu,这里以ubuntu为例子. 一.目录层级结构说明: 1./---------(根目录),所有的目录都挂在其下: 2./boot--------- 存放Ubuntu内核和系统启 ...
- flash小游戏在Kongregate上线——BasketBall Master(篮球大师)
小游戏地址,欢迎上去留言评论.游戏完成度没有达到期望水平,只能算完成了核心玩法吧,一些其他构想来不及实现. BasketBall Master(篮球大师) 这个小游戏很早之前就基本做好了,只因有些细节 ...
- bfs codeforces 754B Ilya and tic-tac-toe game
这题简直把我坑死了 所有的坑都被我中了 题意: 思路:bfs or 模拟 模拟似乎没有什么坑 但是bfs真的是坑 AC代码: #include "iostream" #includ ...
- Python3.5+selenium操作Chrome浏览器
1.安装selenium 命令提示符下输入: pip install selenium 2.下载chromedriver 点击下载 3.将解压后的chromedriver.exe放到chrome浏览器 ...
- Allegro之测量时显示两种单位(mil & mm)
首先确认你工程默认的单位是mil还是mm 例子为mils 在下面的选项中选择另外一项mm即可(如本身是mm,这里选择mils) 点击Apply,然后OK,操作测量功能,如下图所以效果:
- The Myths about Transactions (ACID) and NoSQL
There has been widespread characterization of one of the major distinctions between NoSQL and tradit ...
- iOS 开发快速导引:iOS 程序框架【草】
概要 待补充 App 生命周期 待补充 View Controller 生命周期 待补充 链接 Learn X in Y minutes —— swift 中文版 Learn X in Y minut ...
- IT人生知识分享:博弈论的理性思维
背景: 昨天看了<最强大脑>,由于节目比较有争议性,不知为什么,作为一名感性的人,就想试一下如果自己理性分析会是怎样的呢? 过程是这样的: 中国队(3人)VS英国队(4人). 1:李建东( ...