jQuery源码解读3:.ajax()函数

news/2024/6/27 11:37:48

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

一、从ajax调用出发

$.ajax({
    url:"http://www.microsoft.com",    //设置请求的url
    dataType:"json",   //设置数据返回格式为json
    async:true,//设置请求是否异步,默认为异步。
    data:{"id":"value"},    //设置发送的数据
    type:"GET",   //设置请求方式
    beforeSend:function(){
        //设置请求前的回调
    },
    success:function(req){
        //设置请求成功后的回调
    },
    complete:function(){
        //设置请求完成后的回调
    },
    error:function(){
        //设置请求出错处理的回调
    }
});

从ajax标准的请求调用代码中我们看到传入了一个参数,这个参数是一个对象。对象中定义了XMLHttpRequest对象所需的数据集合。

二、万变不离其宗:了解本质

我们知道.ajax()是jQuery对XMLHttpRequest对象发送HTTP请求的一个js封装接口,所以总归要做一下几部:创建XMLHttpRequest对象,然后open进行tcp链接,其次添加相关的头部信息和定义回调函数等等设置,最后send给服务器并携带相关数据。

xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange=callback;
        xmlhttp.open("POST","test.do",true);
//        // 设置POST请求的请求头
        xmlhttp.setRequestHeader("Content-Type"
            , "application/json");
        xmlhttp.send('password=123&username=mingzi');

三、ajax()在jQuery中哪里定义

如图所示,ajax定义在.extend()函数调用的唯一参数对象中,我们前面解读extend源码的时候知道,如果extend函数中只有一个参数(对象)的时候,这个参数就是源对象,jQuery为目标对象。这样等效于在jQuery对象上扩展这个源对象的所有属性,其中之一的ajax就被扩展到jQuery对象上,成为jQuery静态工具函数的其中一员。

四、拆解.ajax()函数

1.  .ajax()方法执行的6个关键步骤:

1)构造完整的请求选项集,并修正选项。【预处理AJAX所有数据合并用户定义的数据和默认数据】
2)构造jqXHR对象,并增加异步队列的行为。【http头部数据】
3)构造回调函数done(status,nativeStatusText,responses,headers),响应完成之后被调用,负责转换数据类型、执行回调函数、触发全局事件。【回调函数模型,处理所有状态的回调】
4)应用前置过滤器,继续修正选项。【数据处理】
5)获取请求发送器,并调用方法send(requestHeaders,done)发送请求。【创建XMLHttpRequest对象及open、send及回调处理等方法】
6)最后返回jqXHR对象。

2、构造完整的请求选项集

1)传进来的参数对象预处理

A. 如果第一个参数是对象类型,那option 就直接等于 第一个参数 url。然后消灭url = undefined。

B. 通过与一个空对象()进行或运算,强制option为一个对象!

ajax: function( url, options ) {
		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}
		// Force options to be an object
		options = options || {};
        s = jQuery.ajaxSetup( {}, options ),
}

2) 创建最终选项对象(XMLHttpRequest所需的数据集):将传进来的对象与默认选项对象进行深度合并。

A. jQuery.ajaxSetup — ajaxExtend() —— jQuery.ajaxSettings——jQuery.ajaxSettings.flatOptions

B. 简而言之是通过以上的几个函数调用将默认选项对象jQuery.ajaxSettings和用户自定义的ajax参数(选项对象)通过ajaxExtend进行深度合并(除了url和context不深度外),得到一个最终的选项对象s。如下:

3. 构造jqXHR对象

jqXHR对象是浏览器原生XMLHttpRequest对象的超集,当请求发送器不是XMLHttpRequest时,jqXHR对象会尽可能地模拟XMLHttpRequest的功能。并且,jqXHR对象还具备异步队列的方法和行为。为了兼容XMLHttpRequest,jqXHR对象暴露了以下属性和方法:
❑readyState:表示当前jqXHR对象的状态。
❑status:响应的HTTP状态码。
❑statusText:响应的HTTP状态描述。
❑responseText、responseXML:响应的文本内容、XML文档。
❑setRequestHeader(name,value):设置请求头 […]

❑getAllResponseHeaders():获取响应头字符串。
❑getResponseHeader(key):获取指定名称的响应头的值。
❑overrideMimeType(type):用于覆盖MIME类型。
❑abort(statusText):取消本次请求。

4. done构造函数!

1)在.ajax()函数中根据需要直接调用done;

2)传入发送器的send()函数当send的回调函数对发送数据完成后回调执行。

transport.send( requestHeaders, done );
//传入整个done回调函数放到transport.send(参数中
send: function( headers, complete ) {

//定义发送器send中的回调函数Callback
				callback = function( type ) {
					return function() {
						if ( callback ) {
							if ( type === "abort" ) {
								xhr.abort();
							} else if ( type === "error" ) {
									complete( 0, "error" );
							} else {
								complete(
									xhrSuccessStatus[ xhr.status ] || xhr.status,
									xhr.statusText,
									( xhr.responseType || "text" ) !== "text"  ||
									typeof xhr.responseText !== "string" ?
										{ binary: xhr.response } :
										{ text: xhr.responseText },
									xhr.getAllResponseHeaders()

				// Listen to events
//启动回调函数的监听
				xhr.onload = callback();

5、数据处理:应用前置过滤器,继续修正选项

1)常规的:

s.url = ( ( url || s.url || location.href ) + "" )
			.replace( rprotocol, location.protocol + "//" );

		// Alias method option to type as per ticket #12004
		s.type = options.method || options.type || s.method || s.type;

2)应用前置过滤器继续修正选项对象

prefilters = {},//空过滤器

ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),//向对象prefilters中添加前置过滤器

inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );//从对象prefilters中找到数据类型对应的前置过滤器数组,逐个执行

6. 发送器

1)我们可以从以下代码中看到transports发送器中含有XMLHttpRequest对象,及open创建网络链接、send()发送和abort()取消发送方法,还有执行回调函数complete 。

2)一次send的执行:transport.send( requestHeaders, done ); done是一个回调函数模型。可以执行各种http状态的回调!

transports = {},

ajaxTransport: addToPrefiltersOrTransports( transports ),

//通过inspectPrefiltersOrTransports获取发送器
transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

//发送器实体
jQuery.ajaxTransport( function( options ) {
	var callback, errorCallback;

	// Cross domain only allowed if supported through XMLHttpRequest
	if ( support.cors || xhrSupported && !options.crossDomain ) {
		return {
			send: function( headers, complete ) {
//构造XMLHttpRequest对象放在发送器里
				var i,xhr = options.xhr();
				xhr.open(options.type,options.url,options.async,options.username,options.password);
				// Set headers
				for ( i in headers ) {
					xhr.setRequestHeader( i, headers[ i ] );
				}
				// Callback
				callback = function( type ) {
					return function() {
						if ( callback ) {
							callback = errorCallback = xhr.onload =
								xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
							if ( type === "abort" ) {
								xhr.abort();
							} else if ( type === "error" ) {
									complete(
										xhr.status,
										xhr.statusText
									);
								}
							} else {
								complete(
									xhrSuccessStatus[ xhr.status ] || xhr.status,
									xhr.statusText,
									( xhr.responseType || "text" ) !== "text"  ||
									typeof xhr.responseText !== "string" ?
										{ binary: xhr.response } :
										{ text: xhr.responseText },
									xhr.getAllResponseHeaders()
								);
							}
						}
					};
				};
				xhr.onload = callback();
			},

			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}
} );

//构造XMLHttpRequest对象放在发送器里
options.xhr() = jQuery.ajaxSettings.xhr = function() {
	try {
		return new window.XMLHttpRequest();
	} catch ( e ) {}
};

五、总结

转载于:https://my.oschina.net/u/3697586/blog/1551095


http://www.niftyadmin.cn/n/3565951.html

相关文章

wxWidgets之--wxSizer

当我们需要写自己的dialog的时候,需要布置好控件的位置,界面才美观.可是如果控件比较多的化,难道我们需要对每个都指定坐标么?还有一个重要的问题是,这个过程不是"所见即所得"!(当然现在wxWidgets也有可视的界面编辑器了,这里不考虑这个).这个对于从VC/Delphi转过来…

Metafile

Metafile和位图的关系,就像点阵图和位元映射图形(矢量图形)的关系一样。 点阵图通常来自实际的图像,而metafile则大多是通过电脑程式人为建立的。点阵是通过记录像素点的位置描绘图形,而矢量图形是通过数学公式即时演算画出的图形。Metafile由…

Lucene.Net 3.0.3如何从TokenStream中获取token对象

Lucene.Net最高版本为3.0.3,并且apache已经不再提供Lucene.Net的更新,没仔细研究过Lucene.Net的所有版本,Lucene.Net3.0.3遍历TokenStream获取Token对象,已经和以前的版本有了很大的区别,很多方法都已经删除了或者过时…

【Python】 基于秘钥的对称加密

【Crypto】 关于用python进行信息的加密,类似的解决方案有很多比如用base64编码进行encode,再或者是hashlib来进行hash。但是还缺少一种明明场景很简单的解决方案,就是把利用一个秘钥,把一段明文加密然后用同一个秘钥可以把密文解…

使用wxWidgets编程——第一步

译者注:出于个人对wxWindgets的爱好,翻译了此文,总共计8章。在翻译过程中,力求忠实于原文的表达方法。说真的中西方的表达方式真的有很大不同,单独看一个句子是没错误,可放联系上下文,就根本不是…

位图是位的矩形数组

位图是位的矩形数组

python基础 —— 第一个python程序

第一个python程序 编写: hello.py 执行python程序 $ python3 文件路径名.py 常用的文件后缀: .py python语言后缀 .c C语言 .cpp/.cc/.cxx C语言后缀 .java Java语言后缀 在python交互模式下编写并执行代码 进入交互模式:$ python3 <回车&…

设备内容

当您想在一个图形输出设备&#xff08;诸如屏幕或者打印机&#xff09;上绘图时&#xff0c;您首先必须获得一个设备内容&#xff08;或者DC&#xff09;的句柄。