Ajax 处理服务端响应
在浏览器发送 Ajax 请求之后,下一步骤自然是服务器响应。服务器在接收到请求之后会进行一系列处理步骤,最终返回结果。而与此同时,客户端会在接收到返回的结果之后进行界面的展示或者数据的处理。
本章节主讲 Ajax 收到返回数据后处理服务器响应过程。
本章节将会从两个方面来讲解 Ajax 如何处理服务端响应,它们分别是:
- 处理的时机
- 处理的方法
如果你不知道 Ajax 是如何获取服务端响应内容的,或者你对 HTTP 状态码没有一个初步的了解,甚至你还不知道一个 Ajax 请求过程中各个阶段的状态表示,那么,我相信这个章节会很适合你。接下来让我们步入正题,一起来看看 Ajax 是如何处理服务端响应的。
首先思考一个问题,我们应该在什么时机处理服务端的响应呢?
我们知道,Ajax 可以发送异步请求,那数据的返回当然也不可能是同步返回的。客户端只有等到服务端数据返回才能进行数据的下一步处理。如果服务端没有正确响应,或者说服务端的响应还没结束,那么客户端是无法获得正确响应的。讲得俏皮一点,客户端在这个时候还得看服务端的脸色。
那么,在代码中我们要在什么样的时机开始处理响应呢?
这里,我们有必要了解一下 XMLHttpRequest.readyState
和 XMLHttpRequest.status
。
在客户端与服务器的通信过程中,XMLHttpRequest.readyState 体现着当前请求以及服务端响应的状态。当 xhr.readyState == 4
的时候,代表着服务器响应完成。
其他的 readyState 状态码还有 0 、1、2、3,他们分别代表着:
0:状态为 UNSENT。表示创建了但还没有调用 open 方法。
1:状态为 OPENED。表示已经调用了 open 方法。
2:状态为 HEADERS_RECEIVED。表示已经调用了 send 方法,且头部和状态也可获得。
3:状态为 LOADING。表示正在下载中。
4:状态为 DONE。表示响应已经完成。
从 readyState 的状态码来看,总共有 5 个状态。并且只有最后一个状态 4 才能代表着可以开始处理服务端响应数据的时机。
服务器响应完成之后,我们通常会使用 XMLHttpRequest.status 来查看当前 XMLHttpRequest 响应中的数字状态码。这个数字状态码是一个无符号短整型状态码,代表着我们的 Ajax 请求的状态成功与否。
在 XMLHttpRequest 中, status 码对应着标准的 HTTP 状态码。并且在请求完成前,该值为 0。
HTTP 状态码很多,这里就不做过多的铺开,具体可以到 HTTP 响应代码 进行学习和查阅。接下来我们来讲几个常见的状态码。
是的,这也是很常见的两个状态码。
1.2.1 200 和 304 状态码
在 HTTP 状态码中,200 代表着 HTTP 请求成功,而 304 代表着由于浏览器缓存原因,GET 请求命中并返回了缓存中的数据。结合 上面 XMLHttpRequest.readyState , 假设请求成功,我们的响应模块应该如下:
xhr.open("GET", "http://localhost:8080/simple/get?mk=慕课网");
xhr.send();
xhr.onreadystatechange = function() {
// 当前 this 为 xhr
if (this.readyState == 4) {
if (this.status === 200 || this.status === 304) {
// code ...
}
}
};
在后端设置了协商缓存的情况下,我们来看看效果:
第一次请求资源:
刷新页面,进行第二次请求同样的资源:
由于浏览器的缓存机制,GET请求有可能会缓存我们的请求内容。上面前后两次请求中,第一次请求的时候获取新的内容,返回的是 200 的状态码;而第二次再进行获取,我们就有可能获取第二图的结果,使用的是本地缓存。因此,在对 Ajax 成功的判断中,我们不应该遗漏 304 状态码的判断。
1.2.2 404 和 500 状态码
有正确的返回,那当然也会有错误的返回。打个比方,让我们来假设这样的场景:
- 客户端发送一个请求,刚好请求的接口找不到,因为服务端并没有提供。
- 客户端发送一个请求,服务端内部发生错误了。
如果遇到这样的情况,Ajax 当然不能坐以待毙——我们总不该不把任何响应告诉用户吧!真实的情况是,Ajax 会返回我们相应的 status ,客户端根据该 status 进行必要的操作。
首先,我们来请求一个捏造的接口,即服务端并没有支持的接口。
html 关键容器:
<div id="container"></div>
JavaScript 脚本关键代码:
var container = document.getElementById('container')
xhr.onreadystatechange = function() {
// 当前 this 为 xhr
if (this.readyState == 4) {
if (this.status === 200 || this.status === 304) {
container.innerHTML = "当前状态码为: " + this.status;
} else {
container.innerHTML = "当前错误状态码为: " + this.status; // 主要看这里,出现非 200 和 304 状态会在这边进行显示
}
}
};
看看运行后的效果图:
404 Not Found,显而易见,当我们在查询的时候,服务端找不到对应的资源的时候就会返回该状态码,表示你要找的东西没有,不存在。在我们的实际工作中,我们经常会遇到这样的错误,往往这个时候你就应该警惕:
- 是不是你的请求 url 写错了?
- 是不是前后端线上资源不同步?比方说后端还没上线对应接口而你已经在开始在代码中请求了。
讲完 404 状态码,我们接下来继续来看看一个很常见的场景,服务器内部发生错误了!!!代码沿用上一个示例,接口改为服务端提供的接口,这次我们会在服务端假设发生错误,并返回 500 错误。
来看看请求的结果:
事实上,500 错误码也是非常常见的,500 Internal Server Error 代表着服务端错误,如果我们在开发过程中遇到这样的错误,那么,就需要后端的同学来查找原因了。
除此之外,HTTP 状态码还有很多,每个都有不同的含义,这里也不会做过多的展开,有兴趣的同学可以做一个额外的学习查阅。HTTP 协议中,状态码可以让我们在请求之后,获知请求的状态。客户端也能够以此做出相应的响应。
要获取响应内容,当然是 XMLHttpRequest 对象下的几大法器:responseText 、 responseXML 和 response。其中:
- responseText: 一个 DomString,返回一个纯文本的值。 当该值为 “” 的时候,表示这个请求还没有开始
send()
;当该值为 null 的时候,表示请求失败。 - responseXML: 处理 XML 响应。返回一个包含请求检索的 HTML 和 XML 的 Document。 当请求还没有
send()
,或者失败了,甚至是解析失败的时候,该值为 null 。当 responseType 不是 “” 或者 "document"的时候,会报错。 - response: 返回响应正文。返回类型可以有 DOMString、 Blob 、ArrayBuffer 、Document 或 JavaScript Object ,这取决于 responseType。
了解获取响应内容的这 3 个属性,接下来,我们会分别返回 DomString、XML 和 Json 类型数据来展示着响应内容。
核心响应代码:
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status === 200 || this.status === 304) {
var res = this.response
var resText = this.responseText
var resXml = this.responseXML
console.log(res, resText, resXml) // 分别打印三者
}
}
};
2.1 返回 DomString
服务端返回内容:
‘text’
请求结果:
Content-type:
可以看到,当返回的是一个 DomString 的时候,responseText 和 response 都有值,而 responseXML 因为解析失败为 null。
2.2 返回 XML
服务端返回内容:
<data>Hello World</data>
请求结果:
Content-type:
这一次我们的 XML 正常解析了,并且在控制台上可以看到打印出了一个 Document,而 response 和 responseText 分别打印了该 XML 的文本形式。
2.3 返回 Json
服务端返回内容:
{a:1}
请求结果:
Content-type:
当返回的是一个 Json 类型数据的时候,response 和 responseText 分别为对应的文本值,而 responseXML 因为解析失败成了 null。
以上展示了 Ajax 获取服务端响应的三种类型的数据,简单的展示给大家 XMLHttpRequest 的 response、responseText 和 responseXML 在不同数据类型下的表现,希望以此能够加深大家对 XMLHttpRequest 的了解。
- 处理 Ajax 请求,我们应该在适当的时机进行处理。我们应该在
xhr.readyState == 4
,并且xhr.status === 200 || xhr.status === 304
的时候正确获取响应的内容; - XMLHttpRequest.readyState 体现着当前请求以及服务端响应的状态;
- XMLHttpRequest.status 即 XMLHttpRequest 响应中的数字状态码。这个数字状态码是一个无符号短整型状态码,代表着我们的 Ajax 请求的状态成功与否;
- HTTP 状态码有很多,包括 404、 500 等,每一个包含着不一样的含义;
- 获取服务器响应内容,我们可以使用 responseText 、 responseXML 和 response 。其中,responseText 返回一个纯文本的值,responseXML 返回一个包含请求检索的 HTML 和 XML 的 Document,而 response 返回响应正文。返回类型可以有 DOMString、 Blob 、ArrayBuffer 、Document 或 JavaScript Object ,这取决于 responseType。