Ajax 处理服务端响应

在浏览器发送 Ajax 请求之后,下一步骤自然是服务器响应。服务器在接收到请求之后会进行一系列处理步骤,最终返回结果。而与此同时,客户端会在接收到返回的结果之后进行界面的展示或者数据的处理。

本章节主讲 Ajax 收到返回数据后处理服务器响应过程。

前言

本章节将会从两个方面来讲解 Ajax 如何处理服务端响应,它们分别是:

  • 处理的时机
  • 处理的方法

如果你不知道 Ajax 是如何获取服务端响应内容的,或者你对 HTTP 状态码没有一个初步的了解,甚至你还不知道一个 Ajax 请求过程中各个阶段的状态表示,那么,我相信这个章节会很适合你。接下来让我们步入正题,一起来看看 Ajax 是如何处理服务端响应的。

1. 何时处理响应

首先思考一个问题,我们应该在什么时机处理服务端的响应呢?

我们知道,Ajax 可以发送异步请求,那数据的返回当然也不可能是同步返回的。客户端只有等到服务端数据返回才能进行数据的下一步处理。如果服务端没有正确响应,或者说服务端的响应还没结束,那么客户端是无法获得正确响应的。讲得俏皮一点,客户端在这个时候还得看服务端的脸色。

那么,在代码中我们要在什么样的时机开始处理响应呢?

这里,我们有必要了解一下 XMLHttpRequest.readyStateXMLHttpRequest.status

1.1 XMLHttpRequest.readyState

在客户端与服务器的通信过程中,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 才能代表着可以开始处理服务端响应数据的时机

1.2 XMLHttpRequest.status

服务器响应完成之后,我们通常会使用 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 协议中,状态码可以让我们在请求之后,获知请求的状态。客户端也能够以此做出相应的响应。

2. 如何获取响应内容

要获取响应内容,当然是 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 的了解。

3. 小结

  • 处理 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。