总结来源:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
一、什么是ajax
ajax = 异步javascript + xml;
ajax技术是一种在日常开发中必不可缺的技术,它可以替代传统form表单的提交方式,因此可以对提交数据作更好的处理、封装、和验证;它可以在不重新加载页面的条件下,对当前页面作一些动态的修改;最重要的是提供异步的方式完成一些需要查询数据库进行数据验证的需求,这些都体现了它的灵活性,所以深入了解ajax就很有必要了。
二、工作原理
如上图所示也结合实际的工作场景,除了在页面初始化时,使用ajax访问服务端获取初始化数据,往往都是在某个事件被触发后,在事件响应函数中创建XMLHttpRequest对象,通过发送该对象访问服务端,服务端接收并处理该对象中数据,创建Response对象及携带结果数据返回给浏览器,浏览器端根据返回的数据可进行数据渲染的一些操作。
三、ajax剖析
(一)XMLHttpRequest对象
XMLHttpRequest对象是ajax的基础,ajax之所以强大,我想可能就是对该对象进行了很好的封装,所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject),XMLHttpRequest 可以通过url获取数据而无需刷新页面。
1、创建一个XMLHttpRequest对象
var xmlHttpRequest;
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmlHttpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// IE6, IE5 浏览器执行代码
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
还可以通过try{}catch(e){}的方式
var xmlHttpRequest;
try {
//IE7+、Chrome、Firefox、Opera8.0+和Safari
xmlHttpRequest = new XMLHttpRequest();
} catch (e) {
try {
//IE7+
xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
//IE5、6
xmlHttpRequest new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
//提示操作
}
}
}
return xmlHttpRequest;
(二)、XMLHttpRequest的属性
一个小demo
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("GET","/demoRestfull/returnCacheMap",true);
xmlHttpRequest.send();
以上就是一个最简单的使用xmlHttpRequest对象请求服务端的小示例,首先创建XMLHttpRequest对象,利用该对象的open属性定义请求类型(关于get方式与post方式区别,以及中文乱码这里不说了,有时间再总结),url,以及是否异步请求,最后通过send属性向服务端发送请求。
其他属性
1、XMLHttpRequest.readyState
返回一个 XMLHttpRequest 代理当前所处的状态。一个 XHR 代理总是处于下列状态中的一个:
UNSENT
XMLHttpRequest 代理已被创建, 但尚未调用 open() 方法。
OPENED
open() 方法已经被触发。在这个状态中,可以通过 setRequestHeader() 方法来设置请求的头部, 可以调用 send() 方法来发起请求。
HEADERS_RECEIVED
send() 方法已经被调用,响应头也已经被接收。
LOADING
响应体部分正在被接收。如果 responseType
属性是“text”或空字符串, responseText
将会在载入的过程中拥有部分响应数据。
DONE
请求操作已经完成。这意味着数据传输已经彻底完成或失败。
2、XMLHttpRequest.status
返回了XMLHttpRequest响应中的无符号短整形的数字状态码,在请求完成前,status
的值为0
。值得注意的是,如果 XMLHttpRequest 出错,浏览器返回的 status 也为0。
xmlhttp.status的值及解释:
100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本
200——交易成功
201——提示知道新文件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204——请求收到,但返回信息为空
205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206——服务器已经完成了部分用户的GET请求
300——请求的资源可在多处得到
301——删除请求数据
302——在其他地址发现了请求数据
303——建议客户访问其他URL或访问方式
304——客户端已经执行了GET,但文件未变化
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307——申明请求的资源临时性删除
400——错误请求,如语法错误
401——请求授权失败
402——保留有效ChargeTo头响应
403——请求不允许
404——没有发现文件、查询或URl
405——用户在Request-Line字段定义的方法不允许
406——根据用户发送的Accept拖,请求资源不可访问
407——类似401,用户必须首先在代理服务器上得到授权
408——客户端没有在用户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且无进一步的参考地址
411——服务器拒绝用户定义的Content-Length属性请求
412——一个或多个请求头字段在当前请求中错误
413——请求的资源大于服务器允许的大小
414——请求的资源URL长于服务器允许的长度
415——请求资源不支持请求项目格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段
417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求
合起来
500——服务器产生内部错误
501——服务器不支持请求的函数
502——服务器暂时不可用,有时是为了防止发生系统过载
503——服务器过载或暂停维修
504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长
505——服务器不支持或拒绝支请求头中指定的HTTP版本
1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求
xmlhttp.readyState==4 && xmlhttp.status==200的解释:请求完成并且成功返回
3、XMLHttpRequest.onreadstatechange=function(){}
当readyState 发生改变时,就会调用相应的处理函数,这个函数会被用户线程所调用,一次完整的异步请求因readState的值变化会有四次触发这个处理函数,分别是:readState = 0->1 ,1->2, 2->3, 3->4 ,而判断一次请求与响应的成功如代码所示
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.onreadystatechange = function(){
console.log(xmlHttpRequest.readyStatus);
if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
//xmlHttpRequest.responseText 获取返回数据的字符串形式
var data = xmlHttpRequest.responseText;
}
};
xmlHttpRequest.open("GET","/demoRestfull/returnCacheMap,true);
xmlHttpRequest.send();
注意:当设置同步请求时,不需要定义onreadyStatechange的处理函数,直接在最后处理数据数据就可以了,一般不介意用同步的方式,如此可能会处理时间长或请求失败而阻碍用户的进一步操作,具体代码如下:
//此种方式若处理时间过长,或出现异常,会阻碍用户操作
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("GET","/demoRestfull/returnCacheMap?name=小辉&id=2",false);
xmlHttpRequest.send();
//xmlHttpRequest.responseText 获取返回数据的字符串形式
var data = xmlHttpRequest.responseText;
4、XMLHttpRequest.responseType
该属性是一个枚举类型的属性,返回响应数据的类型。它允许我们手动的设置返回数据的类型。如果我们将它设置为一个空字符串,它将使用默认的"text"类型。
当将responseType设置为一个特定的类型时,你需要确保服务器所返回的类型和你所设置的返回值类型是兼容的。那么如果两者类型不兼容,服务器返回的数据变成了null,即使服务器返回了数据。还有一个要注意的是,给一个同步请求设置responseType会抛出一个InvalidAccessError
的异常。
responseType 支持一下几种值
5、XMLHttpRequest.response
该属性返回响应的正文。返回的类型可以是 ArrayBuffer
、 Blob
、 Document
、 JavaScript Object
或 DOMString
。 这取决于 responseType
属性,你可以尝试设置 responseType
的值,以便通过特定的类型请求数据。 responseType
要在调用 open()
初始化请求之后调用, 并且要在调用 send()
发送请求到服务器之前调用。如果请求尚未完成或未成功,则取值是 null
。例外的,读取文本数据时如果将 responseType
的值设置成"text"
或空字符串(""
)且当请求状态还在是 LOADING
readyState
(3) 时,response 包含到目前为止该请求已经取得的内容。
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.onreadystatechange = function(){
//这里可以在浏览器上打个debug看下response在不同readyStatus下的内容
var data = xmlHttpRequest.response;
if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
//根据responseType = "json" 这里返回json格式数据
var data = xmlHttpRequest.response;
console.log(data.name);
}
};
xmlHttpRequest.open("GET","/demoRestfull/returnCacheMap?name=小辉&id=2",true);
xmlHttpRequest.responseType = "json";
xmlHttpRequest.send();
6、XMLHttpRequest.responseText
该属性返回一个DOMString,它包含对文本的请求的响应,如果请求不成功或尚未发送,则返回null。responseText
属性在请求完成之前将会得到部分属性。 如果 XMLHttpRequest.responseType
的值不是 text
或者空字符串,届时访问 XMLHttpRequest.responseType
将抛出 InvalidStateError
异常。
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.onreadystatechange = function(){
//这里可以在浏览器上打个debug看下responseText在不同readyStatus下的内容
var data1 = xmlHttpRequest.responseText;
console.log(xmlHttpRequest.readyState);
if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
//xmlHttpRequest.responseText 获取返回数据的字符串形式
var data = xmlHttpRequest.responseText;
console.log("success");
}
};
xmlHttpRequest.open("POST","/demoRestfull/returnCacheMap",true);
/*xmlHttpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");这里是设置请求头数据*/
xmlHttpRequest.send("name=小莉&id=3");
7、XMLHttpRequest.responseURL
如果URL为空,只读的XMLHttpRequest.responseURL
属性返回响应的序列化URL或空字符串。当URL被返回的时候,任何包含在URL # 后面的fragment都会被删除。 responseURL
的值将会是经过任意多次重定向后的最终 URL 。(注意:这里只是只读,与open方法里设置url性质不同)
8、XMLHttpRequest.timeout
是一个无符号长整型数,代表着一个请求在被自动终止前所消耗的毫秒数。默认值为 0,意味着没有超时。超时并不应该用在一个 document environment 中的同步 XMLHttpRequests 请求中,否则将会抛出一个 InvalidAccessError
类型的错误。当超时发生, timeout 事件将会被触发。最好是在open和send之间设置
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.onreadystatechange = function(){
var data1 = xmlHttpRequest.response;
if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
//xmlHttpRequest.responseText 获取返回的数据
var data = xmlHttpRequest.response;
console.log(data.name);
}
};
xmlHttpRequest.open("GET","/demoRestfull/returnCacheMap?name=小辉&id=2",true);
//超时2秒
xmlHttpRequest.timeout = 2000;
//超时响应
xmlHttpRequest.ontimeout = function () {
console.log("超时了");
}
xmlHttpRequest.responseType = "json";
xmlHttpRequest.send();
9、XMLHttpRequest.upload方法
返回XMLHttpRequestUpload
对象,用来表示上传的进度。这个对象是不透明的,但是作为一个XMLHttpRequestEventTarget
,可以通过对其绑定事件来追踪它的进度。
可以被绑定在upload对象上的事件监听器如下:
三、ajax的优缺点
这里暂时不做总结,暂时记下在项目开发中遇到的问题及解决办法。