jQuery1.5以后,AJAX模块提供了三个新的方法用于管理、扩展AJAX请求,分别是:

1.前置过滤器 jQuery. ajaxPrefilter

2.请求分发器 jQuery. ajaxTransport,

3.类型转换器 ajaxConvert

源码结构:

jQuery.extend({

    /**
* 前置过滤器
* @type {[type]}
*/
ajaxPrefilter: addToPrefiltersOrTransports(prefilters), /**
* 请求分发器
* @type {[type]}
*/
ajaxTransport: addToPrefiltersOrTransports(transports), ...........................
});

可见这2个方法是通过私有方法addToPrefiltersOrTransports通过curry手段构造的,分别是保持了prefilters与transports的引用


来个简单的模拟这个结构

var prefilters = 2;

var addToPrefiltersOrTransports = function(prefilters) {
return function(b) {
return prefilters + b;
}
} var ajaxPrefilter = addToPrefiltersOrTransports(prefilters) ajaxPrefilter(1) //

可见ajaxPrefilter就维持了addToPrefiltersOrTransports返回函数的引用了,这种就是闭包的手法了,这也是JS的开发人员都需要掌握的

好处就是合并多个参数,当然因为维持引用代价就是一点点性能消耗

当然jQuery不是传递的简单类型处理,还可以传递的一个引用类型的回调函数,所以针对ajaxPrefilter方法放闭包构件就需要做一些处理了

填充prefilters处理器

var prefilters = {};

var addToPrefiltersOrTransports = function(structure) {

    return function(func) {
structure['*'] = func;
}
} var ajaxPrefilter = addToPrefiltersOrTransports(prefilters) ajaxPrefilter(function(options){
return {
send:function(){ },
callback:function(){ }
}
})

其实说白了就是把对应的方法制作能函数的形式填充到prefilters或者transports对应的处理包装对象中

要用的时候直接执行,每个函数都保持着各自的引用

这种写法的好处自然是灵活,易维护,减少代码量

还有我们经常的使用的,jQuery的代码很简练,比如合并多个方法的创建等等

jQuery.each([
"tabIndex",
"readOnly",
"maxLength",
"contentEditable"
], function() {
jQuery.propFix[this.toLowerCase()] = this;
});

所以此时的prefilters中的结构就是

prefilters = {
'*': function() {
return {
send: function() { },
callback: function() { }
}
}
}

回归重点,那么引入ajaxPrefilter与ajaxTransport的作用是干嘛?

前置过滤器和请求分发器在执行时,分别遍历内部变量prefilters和transports,这两个变量在jQuery加载完毕后立即初始化,从过闭包的方法填充这个2个对象

ajaxPrefilter与ajaxTransport都是通过inspectPrefiltersOrTransports构建器

prefilters中的前置过滤器在请求发送之前、设置请求参数的过程中被调用,调用prefilters的是函数inspectPrefiltersOrTransports;

巧妙的是,transports中的请求分发器在大部分参数设置完成后,也通过函数inspectPrefiltersOrTransports取到与请求类型匹配的请求分发器:

function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR) {

    var inspected = {},
seekingTransport = (structure === transports); function inspect(dataType) {
var selected;
inspected[dataType] = true;
jQuery.each(structure[dataType] || [], function(_, prefilterOrFactory) {
var dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR);
if (typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[dataTypeOrTransport]) {
options.dataTypes.unshift(dataTypeOrTransport);
inspect(dataTypeOrTransport);
return false;
} else if (seekingTransport) {
return !(selected = dataTypeOrTransport);
}
});
return selected;
} return inspect(options.dataTypes[0]) || !inspected["*"] && inspect("*");
}

遍历structure[dataType]数组,并执行回调
prefilterOrFactory为函数数组元素

执行该函数如果返回的结果dataTypeOrTransport是字符串且时prefilters且没有被inspected过

就给options.dataTypes数组头部添加该字符串

继续递归dataTypeOrTransport(当我们使用json/jsonp的时候会返回“script”,于是会执行“script”相关的回调)

如果是transport就返回dataTypeOrTransport的假结果


前置过滤器 prefilters

简单的说就是一种hack的做法,只是说比起事件的那种hack写的手法实现更为高明

我们可以看看针对prefilters的方法其实就是dataType为 script,json,jsonp的处理

当我们动态加载脚本文件比如

$.ajax({
type : "GET",
url : "test.js",
dataType : "script"
});

所以在inspectPrefiltersOrTransports方法中prefilters[script]能找到对应的处理方法,所以就会执行

例如script的hack,要强制加上处理缓存的特殊情况和crossDomain

因为设置script的前置过滤器,script并不一定意思着跨域

跨域未被禁用,强制类型为GET,不触发全局时间

jQuery.ajaxPrefilter("script", function(s) {
if (s.cache === undefined) {
s.cache = false;
}
if (s.crossDomain) {
s.type = "GET";
}
});

所以prefilters就是在特定的环境针对特定的情况做一些必要的兼容的处理


请求分发器 transports

请求分发器顾名思义发送请求,那么底层的ajax发送请求是通过send方法

xhr.send();

但是jQuery对send方法做了拆分,把对应的处理放到了transports中了

那么transports对象也是类似前置处理器通过jQuery.ajaxTransport构建

例如script,send,abort方法

返回出transports方法

transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);

jQuery源码分析系列(33) : AJAX中的前置过滤器和请求分发器的更多相关文章

  1. jQuery源码分析系列(34) : Ajax - 预处理jsonp

    上一章大概讲了前置过滤器和请求分发器的作用,这一章主要是具体分析每种对应的处理方式 $.ajax()调用不同类型的响应,被传递到成功处理函数之前,会经过不同种类的预处理(prefilters). 预处 ...

  2. jQuery源码分析系列(36) : Ajax - 类型转化器

    什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...

  3. jQuery源码分析系列(37) : Ajax 总结

    综合前面的分析,我们总结如下3大块: jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求 前置过滤器 jQuery. ajaxPrefilter 请求分发器 jQuery ...

  4. jQuery源码分析系列(31) : Ajax deferred实现

    AJAX的底层实现都是浏览器提供的,所以任何基于api上面的框架或者库,都只是说对于功能的灵活与兼容维护性做出最优的扩展 ajax请求的流程: 1.通过 new XMLHttpRequest 或其它的 ...

  5. jQuery源码分析系列(30) : Ajax 整体结构

    开头引用一段 想起一句话:前端研究,研究个屁~ 的确如此呀.补充下联:前端设计,设计个屁~ 前端目前最大的困境是,如 HTML 一样,无论你承不承认,市场上并不太需要 HTML 高手 其实这里引发一个 ...

  6. jQuery源码分析系列(35) : Ajax - jsonp的实现与原理

    ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本 json核心就是:允许用户传递一个callba ...

  7. jQuery源码分析系列(转载来源Aaron.)

    声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...

  8. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  9. [转]jQuery源码分析系列

    文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...

随机推荐

  1. ubuntu14.04+nvidia driver+cuda8+cudnn5+tensorflow0.12

    文章在简书里面编辑的,复制过来貌似不太好看,还是到简书的页面看吧: http://www.jianshu.com/p/c89b97d052b7 1.安装环境简介: 硬件: cpu:i7 6700k g ...

  2. js截取中英文字符串、标点符号无乱码示例解读

    <script> function subString(str, len, hasDot) { var newLength = 0; var newStr = ""; ...

  3. .net core 产品开发问题记录

    背景 最近在公司的一个产品研发中,最终还是选择了以.net core 作为主要的技术方案.本文会拟记录开发过程中于以往中区别比较大,或者可能造成的坑. 程序集无法引用本地程序集 .net core 的 ...

  4. 【贪心】HDU 1257

    HDU 1257 最少拦截系统 题意:中文题不解释. 思路:网上有说贪心有说DP,想法就是开一个数组存每个拦截系统当前最高能拦截的导弹高度.输入每个导弹高度的时候就开始处理,遍历每一个拦截系统,一旦最 ...

  5. tornado 学习笔记17 HTTPServerRequest分析

         代表Http请求.      所有的属性都是字符串型. 17.1 属性 (1) method:请求方法类型,比如"GET"."POST" (2) ur ...

  6. 速度极快的导出excel

    public class Export2Excel { #region [导出文件,使用文件流] /// <summary> /// 导出文件,使用文件流.该方法使用的数据源为DataTa ...

  7. (转)python requests的安装与简单运用

    requests是python的一个HTTP客户端库,跟urllib,urllib2类似,那为什么要用requests而不用urllib2呢?官方文档中是这样说明的: python的标准库urllib ...

  8. linux终端 字符界面 显示乱码

    方法一:配置SSH工具 SecureCRT中文版配置 [全局选项]→[默认会话]→[编辑默认设置]→[终端]→[外观]→[字体]→[新宋体 10pt CHINESE_GB2312]→[字符编码 UTF ...

  9. zend studio8编辑器乱码问题解决办法

    截图一张:

  10. 关于mysql ERROR 1045 (28000)错误的解决办法

    错误情景: 使用Navicat打开mysql的时候弹出错误框 错误代码: ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' ( ...