XMLHttpRequest 说明

https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
XMLHttpRequest 对象,主要用于发送http请求给后端

使用方式

1、创建XHR 对象

所有现代浏览器都通过 XMLHttpRequest 构造函数原生支持 XHR 对象

  1. let xhr = new XMLHttpRequest();

2、基本配置

使用 XHR 对象首先要调用 open( )方法,对本次发送的请求进行配置。

调用 open()不会实际发送请求,只是为发送请求做好准备。

  1. xhr.open("get", "example.php", false); // 这行代码就可以向 example.php 发送一个同步的 GET 请求。

这个方法接收 3 个参数:
1、请求类型(”get”、”post”等)

2、请求 URL,
(1)这里的 URL 是相对于代码所在页面的,当然也可以使用绝对 URL
(2)只能访问同源 URL,也就是域名相同、端口相同、协议相同。如果请求的 URL 与发送请求的页面在任何方面有所不同,则会抛出安全错误

3、请求是否异步的布尔值。

3、配置接收服务器响应后执行

通过 onreadystatechange 方法,配置收到服务器响应后要执行的方法,见下面的 6、收到服务器的响应

4、发送给服务器

要发送定义好的请求,必须像下面这样调用 send()方法

  1. xhr.send(null);

send()方法接收一个参数,是作为请求体发送的数据。如果不需要发送请求体,则必须传 null,因为这个参数在某些浏览器中是必需的。

调用 send()之后,请求就会发送到服务器。

如果这个请求是同步的,所以 JavaScript 代码会等待服务器响应之后再继续执行。

5、服务器收到请求并返回数据

6、收到服务器的响应

收到响应后,XHR对象的以下属性会被填充上数据:
responseText:作为响应体返回的文本。
responseXML:如果响应的内容类型是”text/xml”或”application/xml”,那就是包含响应数据的 XML DOM 文档。
status:响应的 HTTP 状态,如成功是200,url地址不存在就是404等。
statusText:响应的 HTTP 状态描述。

  1. if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
  2. // 2、如果成功,responseText 或 responseXML(如果内容类型正确)属性中会有内容,此时可以显示响应体responseText
  3. alert(xhr.responseText);
  4. } else {
  5. // 3、如果不成功,检查响应的 HTTP 状态
  6. alert("Request was unsuccessful: " + xhr.status);
  7. }

XHR 对象有一个 readyState 属性,表示当前处在请求/响应过程的哪个阶段。
这个属性有如下可能的值:
0:未初始化(Uninitialized)。尚未调用 open()方法。
1:已打开(Open)。已调用 open()方法,尚未调用 send()方法。
2:已发送(Sent)。已调用 send()方法,尚未收到响应。
3:接收中(Receiving)。已经收到部分响应。
4:完成(Complete)。已经收到所有响应,可以使用了。

每次 readyState 从一个值变成另一个值,都会触发 readystatechange 事件。

可以借此机会检查 readyState 的值。一般来说,我们唯一关心的 readyState 值是 4,表示数据已就绪。

为保证跨浏览器兼容,onreadystatechange 事件处理程序应该在调用 open()之前赋值。

  1. // 1、创建
  2. let xhr = new XMLHttpRequest();
  3. // 2、基本配置
  4. xhr.open("get", "example.txt", true);
  5. // 3、配置接收服务器响应后要执行什么
  6. xhr.onreadystatechange = function() {
  7. // 3.1 检查状态,看是否请求完成
  8. if (xhr.readyState == 4) {
  9. // 3.2 检查请求的状态
  10. // 一般来说,HTTP 状态码为 2xx 表示成功
  11. // 如果 HTTP状态码是 304,则表示资源未修改过,是从浏览器缓存中直接拿取的。当然这也意味着响应有效。
  12. if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
  13. // 展示服务器返回的内容
  14. alert(xhr.responseText);
  15. } else {
  16. alert("Request was unsuccessful: " + xhr.status);
  17. }
  18. }
  19. };
  20. // 4、发送
  21. xhr.send(null);

7、取消(可选)

在收到响应之前如果想取消异步请求,可以调用 abort()方法

  1. xhr.abort();

调用这个方法后,XHR 对象会停止触发事件,并阻止访问这个对象上任何与响应相关的属性。

中断请求后,应该取消对 XHR 对象的引用。

由于内存问题,不推荐重用 XHR 对象。

HTTP header 请求头信息

通用信息

image.png(谷歌浏览器按F12可以查看DevTools调试器)
每个 HTTP 请求和响应都会携带一些头部字段,这些字段可能对开发者有用。

XHR 对象会通过一些方法暴露与请求和响应相关的头部字段。

默认情况下,XHR 请求会发送以下头部字段。

accept:浏览器可以处理的内容类型。
accept-charset:浏览器可以显示的字符集。
accept-encoding:浏览器可以处理的压缩编码类型。
accept-language:浏览器使用的语言。
connection:浏览器与服务器的连接类型。
cookie:页面中设置的 Cookie。
host:发送请求的页面所在的域。
referer:发送请求的页面的 URI。注意,这个字段在 HTTP 规范中就拼错了,所以考虑到兼容性也必须将错就错。(正确的拼写应该是 Referrer。)
user-agent:浏览器的用户代理字符串。

设置信息

不同浏览器发送的请求头可能会不一样,但是通用的部分应该都是有的。

如果需要发送额外的请求头部,可以使用 setRequestHeader()方法。
这个方法接收两个参数:头部字段的名称和值。

为保证请求头部被发送,必须在 open()之后、send()之前调用 setRequestHeader()

  1. // 1、创建
  2. let xhr = new XMLHttpRequest();
  3. xhr.onreadystatechange = function() {
  4. if (xhr.readyState == 4) {
  5. if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
  6. alert(xhr.responseText);
  7. } else {
  8. alert("Request was unsuccessful: " + xhr.status);
  9. }
  10. }
  11. };
  12. // 2、准备
  13. xhr.open("get", "example.txt", true);
  14. // 设置自定义头部信息
  15. xhr.setRequestHeader("MyHeader", "MyValue");
  16. // 3、发送
  17. xhr.send(null);

设置请求头的意义,一般有2点:
1、设置 content-type :告诉客户端实际返回的内容的内容类型,这点很重要,会影响到后端服务器怎么去解析你的数据,否则可能会导致后端拿不到数据。
这里设置的内容可以查看:https://www.yuque.com/yejielin/mypn47/lq4be4
一般就是application/json(表示json格式的数据),或者x-www-form-urlencoded (表示是url编码后的数据)等

2、设置 自定义请求头:比如有的后端会规定身份令牌(Token)需要放在请求头里面,而不是放在数据里面进行传输,此时就需要设置请求头。

GET 请求

最常用的请求方法是 GET 请求,用于向服务器查询某些信息。

必要时,需要在 GET 请求的 URL后面添加查询字符串参数。

对 XHR 而言,查询字符串必须正确编码后添加到 URL 后面,然后再传给open()方法。

  1. xhr.open("get", "example.php?name1=value1&name2=value2", true);
  2. // 可以使用以下函数将查询字符串参数添加到现有的 URL 末尾
  3. function addURLParam(url, name, value) {
  4. url += (url.indexOf("?") == -1 ? "?" : "&");
  5. url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
  6. return url;
  7. }

可以使用这个函数构建请求 URL

  1. let url = "example.php";
  2. // 添加参数
  3. url = addURLParam(url, "name", "Nicholas");
  4. url = addURLParam(url, "book", "Professional JavaScript");
  5. // 初始化请求
  6. xhr.open("get", url, false);

POST 请求

第二个最常用的请求是 POST 请求,用于向服务器发送应该保存的数据。

每个 POST 请求都应该在请求体中携带提交的数据,而 GET 请求则不然。

POST 请求的请求体可以包含非常多的数据,而且数据可以是任意格式。

要初始化 POST 请求,open()方法的第一个参数要传”post”,

  1. xhr.open("post", "example.php", true);
  2. xhr.send("要发送的数据")

默认情况下,对服务器而言,POST 请求与提交表单是不一样的。

服务器逻辑需要读取原始 POST数据才能取得浏览器发送的数据。

不过,可以使用 XHR 模拟表单提交。

  1. function submitData() {
  2. let xhr = new XMLHttpRequest();
  3. xhr.onreadystatechange = function() {
  4. if (xhr.readyState == 4) {
  5. if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
  6. alert(xhr.responseText);
  7. } else {
  8. alert("Request was unsuccessful: " + xhr.status);
  9. }
  10. }
  11. };
  12. xhr.open("post", "postexample.php", true);
  13. // 1、需要把 Content-Type 头部设置为"application/x-www-formurlencoded",这是提交表单时使用的内容类型
  14. xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  15. let form = document.getElementById("user-info");
  16. // 2、创建对应格式的字符串
  17. xhr.send(serialize(form));
  18. }

POST 请求相比 GET 请求要占用更多资源。从性能方面说,发送相同数量的数据,GET 请求比 POST 请求要快两倍。

=================

第三方库

Axios

原理是使用XMLHttpRequest 对象发送网络请求,在此基础上包装了Promise和一些方法(如拦截请求、拦截响应等),是现代较为流行的网络请求库之一。

以前Vue团队自己也开发了网络请求的库,后来不维护了,而是推荐使用Axios这个库。

https://www.yuque.com/yejielin/mypn47/ai62gr