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请求,分别是:
$.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
对象将公开下列属性和方法:
readyState
status
statusText
responseXML
and/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)
待续....
本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3713016.html,如需转载请自行联系原作者
jQuery源码分析系列(31) : Ajax deferred实现相关推荐
- jQuery源码分析系列(37) : Ajax 总结
综合前面的分析,我们总结如下3大块: jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求 前置过滤器 jQuery. ajaxPrefilter 请求分发器 jQuery ...
- 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源码分析系列:.domManip() .buildFragment() .clean()
.domManip(args,table,callback):是jQuery DOM操作的核心函数,可以扩展出如下方法: append/appendTo: prepend/prependTo: b ...
- jQuery源码分析系列:属性操作
属性操作 1.6.1相对1.5.x最大的改进,莫过于对属性.attr()的重写了.在1.6.1中,将.attr()一分为二: .attr()..prop(),这是一个令人困惑的变更,也是一个破坏性的升 ...
- jQuery源码分析系列 : 整体架构
query这么多年了分析都写烂了,老早以前就拜读过, 不过这几年都是做移动端,一直御用zepto, 最近抽出点时间把jquery又给扫一遍 我也不会照本宣科的翻译源码,结合自己的实际经验一起拜读吧! ...
- jQuery源码分析系列:事件模块概述
jQuery的事件模块是较复杂的,前面仅仅提到了对事件对象的包装.即统一了一些兼容性的问题.这篇会综述下jQuery的整个事件模块.后面会详细分析jQuery.event.add/jQuery.eve ...
- jQuery源码分析系列目录
jQuery是对JavaScript的最佳实践的产物,这么好的东西阅读后一定会有感悟,还是要拿出来和大家分享滴,从今天开始阅读jQuery并将笔记进行记录,每天更新 1. 简便使用jQuery-源码阅 ...
- jQuery源码分析系列(二)Sizzle选择器引擎-上
前言 我们继续从init()方法中的find()方法往下看, jQuery.find = Sizzle; ...find: function (selector) {/** ... */ret = t ...
- jQuery源码分析系列(一)初识jQuery
一个工厂 (function(global, factory){"use strict"// operation_1 })(typedef window !== "und ...
最新文章
- OpenCV 笔记(02)— 图像显示、保存、腐蚀、模糊、canny 边缘检测(imread、imshow、namedWindow、imwrite)
- Windows phone 7更新已经支持复制/粘贴[有图有真相]
- Excel超级链接方式应用技巧
- Text模式和PDU模式的区别
- Xilinx FPGA单端时钟设计方法
- delphi解析json(解决乱码问题)
- Web前端开发要掌握的技能有哪些?
- win10下cuda、cudnn、c++的cuda环境(build tool of Visual Studio 2019)、anaconda的pytorch-gpu环境、gcc编译环境
- 大数据发展现状和趋势
- 关于使用FileZilla软件出现中文乱码解决方法
- 计算机网络超级详细的总结(2)
- 台式计算机显卡是哪个好,台式电脑显卡排行榜
- android实现跑马灯效果,Android用过TextView实现跑马灯效果的示例
- 【MW】Drop Materialized View Hangs with 'Enq: JI - Contention'
- mac键盘图标与对应快捷按键
- mac和windows下载安装redis
- (小技巧) 如何让Linux 机器CPU使用率变高
- 【IT行业常见缩写】IT行业常见缩写(程序员专用)
- 计算机专业 本科论文,计算机专业本科论文范文
- line android 英文版,LINE 手機版也有深色模式啦!更新完我要去哪裡設定呢?Android/iOS 都有! (1/8 更新)...
热门文章
- linux 历史命令列表,LinuxShell命令history
- PyTorch1.4安装(Anaconda3 + Python3.6 + cpu版本)
- 抓包教程_最简单的Wireshark抓包TCP/UDP新手5步教程(宽带故障运维必备)
- timimg学习数据删了_如何评价Timing这个督促人学习的软件?
- proteus微型计算机梯形波,接口芯片dac0832的应用 三角波、梯形波两种波形.doc
- C++ map, 运用map统计单词出现的次数
- 关于领域模型与技术架构的关系的思考
- CSS的position属性
- (转)webstorm快捷键
- 数据库、连接-mysql学习笔记二-by小雨