AJAX & XMLHttpRequest
Posted Turbo的札记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AJAX & XMLHttpRequest相关的知识,希望对你有一定的参考价值。
全名Asynchronous javascript and XML。
而AJAX这种技术,是通过JavaScript的异步通信,从服务器获取数据,再通过脚本部分更新页面,不用刷新整个页面。简言之就是 通过脚本发起的HTTP通信 (本质),然后拿到响应数据取更新页面。
至于全名中的XML,指的是脚本发起通信后,服务器返回的数据是储存在XML文档中,但这已经是历史了,现在早已弃用XML,服务器传来的数据一般是JSON格式,但这种叫法一直沿用下来。
网速慢时,应用AJAX技术只是更新部分内容,用户可以浏览其余内容;
传统方法提交表单后若内容不合格页面会被刷新,要重新填写所有内容;
传统页面更新页面内容要重新载入页面,然而有些内容是重复的,会造成资源浪费、增加用户等待时间......
新闻应用信息流中下拉加载更多新闻;
列表数据无刷新分页;
表单项离开焦点后对数据进行不刷新页面的实时验证;
搜索框根据已输入的关键字提供联想补全备选项......(本质都是在不刷新页面的情况下部分更新页面)
把他单纯的理解为通过JavaScript发起HTTP通信的方式即可,事实也是如此,下面全文基本是围绕XMLHttpRequest这个JavaScript的原生类展开的,关注的重点在于JS提供了一个实现HTTP通信的原生类,不关AJAX的事儿。
-
创建XMLHttpRequest实例
-
发出HTTP请求 -
接受服务器传回数据 -
更新网页数据
var xhr = new XMLHttpRequest();
xhr.open(
string method, //HTTP方法
string url, //发送请求的目标URL
optional boolean async, //表示是否异步,默认值true,如果是false的话,只有与服务器连接建立后收到服务器响应后,才会进行后面的的代码,同步AJAX请求会造成服务器失去响应。许多浏览器已经禁止在主线程使用,只允许Worker里面使用。所以,这个参数轻易不应该设为false。
optional string user, //用于认证的永明,默认为空字符串。
optional string password//用于认证的密码,默认空字符串
);
-
用于设置HTTP请求得头信息。该方法得调用必须在open之后,send之前。 -
方法接受两个参数,第一个是字符串,写字段名,第二个写字段值。 -
如果重复设置同一个字段,每一次调用的值会被合并成一个单一的值发送。 -
该方法可选,也就是说可以不设置头信息,没有设置得头信息字段会取默认值。
-
用来指定 MIME 类型,覆盖服务器返回的真正的 MIME 类型,从而让浏览器进行不一样的处理。举例来说,服务器返回的数据类型是text/xml,由于种种原因浏览器解析不成功报错,这时就拿不到数据了。为了拿到原始数据,我们可以把 MIME 类型改成text/plain,这样浏览器就不会去自动解析,从而可以拿到原始文本。 -
接受一个字符串类型参数,同样要在open后send前调用,该方法亦是可选。 -
修改服务器返回的数据类型,不是正常情况下应该采取的方法。如果希望服务器返回指定的数据类型,可以用responseType属性告诉服务器(详见后)。只有在服务器无法返回某种数据类型时,才使用该方法。
-
send方法用于发出HTTP请求以及获取请求数据,该方法的参数即请求报文中的请求数据。 -
和请求报文的请求数据一样,数据可以是各种格式,可以是文件,这就是前文提到的AJAX上传文件。 //不过传文件要用到formData,这里就不岔开话题了。 -
在open同服务器建立连接后,用send发出实际的HTTP请求,他的参数是可选的,但没有参数就要输入null,如果不带参数就表示HTTP请求只有一个URL,没有数据体,例如GET请求,反之例如POST请求。 -
open、send两个必须方法依次调用,共同构成了上文提到的发送HTTP请求这一步。 -
虽然没有写HTTP报文,其实调用这几个方法的过程也算是写了:open→请求行,setRequestHeader→请求头,send→请求数据。
-
用来终止已经发出的HTTP请求,该方法没有参数,对实例调用后,会终止实例对应的HTTP请求。 -
调用这个方法以后,readyState属性变为4,status属性变为0(详见后)。 -
说是停止HTTP请求,但实际上整个HTTP通信、整个AJAX过程都被停掉了。调用这个方法后,除了上面两条,还发生了这些事:对应的XHR实例会停止触发事件、不再允许访问任何与响应有关的对象属性(详见后)、终止请求之后还会对XHR对象进行解引用操作。可以这样说,abort()方法调用后,这个XHR对象已经不能用了。
-
由上面三条及二次调用open()方法的效果可知,在同一XMLHttpRequest对象的实例上连续发起两次HTTP/AJAX通信是行不通的,语法不支持这样,请再new一个新的实例。
-
参数为一个字符串,内容为响应消息的头信息字段。用来获取响应报文头信息中指定字段的值。 -
如果未收到服务器回应或指定字段不存在,返回null。 -
如果多个字段同名,它们的值会被连接为一个字符串,每个字段之间使用“逗号+空格”分隔。
-
没有参数,返回一个字符串,字符串内为服务器响应的全部头信息。 -
每个字段间用CRLF分隔(回车+换行)。 -
未收到服务器响应或发生网络错误等,返回空字符串。
|
|
|
|
|
|
|
|
|
|
XMLHttpRequest.responseText,
XMLHttpRequest.responseXML
-
response属性保存了服务器返回的数据体(响应正文),如果本次请求不成功或数据不完整属性等于null。
-
responseType属性是一个字符串,保存了返回的数据体(response)的数据类型。 -
responseType属性是可写的,open之后send之前,设置该值,告诉服务器希望返回的指定类型。若不设置则默认为空字符串,等同于text。上文的方法是用来覆盖响应后的数据体类型,该属性则是在请求时指定希望得到的数据类型。(但请求之后、全程都可以访问)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
至于responseText和responseXML,在这之前需要先补充一些信息:客户端与服务端之间的数据交互是需要编码解码的,不论是responseType属性还是overrideMimeType方法,都是在告诉客户端在拿到服务端的数据后,按照哪种格式来解码,解码后将的到的内容储存在response属性中,即上表含义中表述的样。 -
而responseText则是不看Type的值,将得到的数据按照字符串的类型解析并保存在该属性中,也就是说如果数据是一个二进制类型的结果,访问该属性大概率得到的是乱码。 -
responseXML属性也是同理,浏览器将得到的数据按照html/XML文档对象的类型进行解析,如果请求不成功或收到的数据不是这个类型的,该属性等于null。 -
所以responseXML属性生效的前提必须是响应头信息Content-Type字段的值为text/xml或application/xml,并且responsType属性值为document,否则需要调用overrideMimeType方法强制进行XML解析,不然改属性的值为null。 -
这两个属性都是只读,并且HTTP请求完成接收后属性才会包含完整的数据。
-
属性为字符串,表示发送数据的服务器网址。 -
这个值不见得和open方法指定的请求网址相同,如果服务端发生跳转,这个属性返回最后实际返回数据的网址;另外,如果原始 URL 包括锚点(fragment),该属性会把锚点剥离。
-
这两个属性用于获取响应状态相关信息,status为整数储存了状态码,statusText为字符串储存了状态码的文本描述。 -
请求发出前status值为0。
-
布尔值,表示跨域请求时,用户信息(比如 Cookie 和认证的 HTTP 头信息)是否会包含在请求之中,默认为false,即向index.com发出跨域请求时,不会发送index.com设置在本机上的 Cookie(如果有的话)。同源请求不要设置这个属性。 -
为了让这个属性生效,服务器必须显式返回Access-Control-Allow-Credentials:true 这个头信息。 -
withCredentials属性打开的话,跨域请求不仅会发送 Cookie,还会设置远程主机指定的 Cookie。反之也成立,如果withCredentials属性没有打开,那么跨域的 AJAX 请求即使明确要求浏览器设置 Cookie,浏览器也会忽略。 -
注意,脚本总是遵守同源政策,无法从document.cookie或者 HTTP 回应的头信息之中,读取跨域的 Cookie,withCredentials属性不影响这一点。
-
属性值为一个整数,可读写,单位为毫秒,表示多少毫秒后,若是请求还未得到结果,就会自动终止,同时触发timeout事件(如果有的话,详见后)。 -
未设置改属性或属性值等于0,则表示没有时间限制。
var xhr = new XMLHttpRequest();
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = oEvent.loaded / oEvent.total;
} else {
console.log('无法计算进展');
}
}
xhr.addEventListener('progress', updateProgress);
xhr.open();
-
其实这是一个属性,只不过属性的值是一个对象,我们只能用这个对象的事件,并不能直接用这个对象。 -
XMLHttpRequest.upload属性可以得到一个对象,或者说指向一个对象,通过监听这个对象的事件可以得知客户端向服务端上传数据、文件的进度(即send方法的参数)。 -
话句话说,send方法在进行、向服务端上传数据、文件时也是有各个阶段的,每个阶段会触发XMLHttpRequest.upload这个对象类型的属性的各种事件。 -
该对象可被监听的事件有:loadstart、loadend、load、abort、error、progress、timeout。这些事件和上面高度重合,含义也都是高度相似的,不在赘述。
所以要把一些重复的代码,封装到你自己的一个函数里,同时这个函数还要具有一定的拓展性,满足一些个别的需求。这样你每次调用你自己写的AJAX函数给函数传参即可。
【其实这个轮子已经早有人造好了,JQuery有这个方法,但你还是有必要自己去写写。
-
本文主要参考了阮一峰的JavaScript教程,参考了其中的叙述思路、大量说法,但很大程度上已经超出了参考,属于演绎再创作。
-
在上面的过程中对其表述有误、模糊、繁琐的地方进行了修改,这一部分参考了《Nicholas C.Zakas,JavaScript高级程序设计》,以及大量博客。
以上是关于AJAX & XMLHttpRequest的主要内容,如果未能解决你的问题,请参考以下文章