一、XMLHttpRequest对象

1、使用XHR

  • open()方法
    • 接收3个参数:请求类型、请求URL、表示请求是否异步的布尔值。
    • 调用open不会实际发送请求,只是为发送请求做好准备。
  • send()方法用于发送定义好的请求
    • 方法接收一个参数:作为请求体发送的数据
    • 该请求为同步请求,JavaScript代码会等待服务器响应之后再继续执行。
1
2
3
let xhr = new XMLHttpRequest(); 
xhr.open("get", "example.php", false);
xhr.send(null);
  • 收到响应后,XHR对象的以下属性会被填充上数据。
  • 收到响应后,第一步要检查status属性以确保响应成功返回。

    • 一般来说,HTTP 状态码为2xx表示成功。此时,responseText 或responseXML (如果内容类型正确)属性中会有内容。
    • 如果HTTP状态码是304,则表示资源未修改过,是从浏览器缓存中直接拿取的。当然这也意味着响应有效。
  • XHR对象有一个readyState属性,表示当前处在请求/响应过程的哪个阶段。属性有如下可能的值:

  • 每次readyState从一个值变成另一个值,都会触发readystatechange事件。为保证跨浏览器兼容,onreadystatechange事件处理程序应该在调用open()之前赋值。

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

2、HTTP头部

  • 默认情况下,XHR请求会发送以下头部字段。
  • setRequestHeader方法可以发送额外的请求头部。
    • 接收两个参数:头部字段的名称和值。
    • 为保证请求头部被发送,必须在open()之后、send()之前调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
let xhr = new XMLHttpRequest(); 
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "example.php", true);
xhr.setRequestHeader("MyHeader", "MyValue");
xhr.send(null);
  • getResponseHeader()方法可以从XHR对象获取响应头部。
  • getAllResponseHeaders()方法获取所有响应头部。
1
2
let myHeader = xhr.getResponseHeader("MyHeader"); 
let allHeaders xhr.getAllResponseHeaders();

3、GET请求

  • GET请求用于向服务器查询某些信息。必要时,需要在GET请求的URL后面添加查询字符串参数。
  • 对XHR而言,查询字符串必须正确编码后添加到URL后面,然后再传给open()方法。
  • 查询字符串中的每个名和值都必须使用encodeURIComponent ()编码,所有名/值对必须以和号(&)分隔。
1
xhr.open("get", "example.php?name1=value1&name2=value2", true); 

4、POST请求

  • POST请求,用于向服务器发送应该保存的数据。
  • 每个POST请求都应该在请求体中携带提交的数据,而GET请求则不然。
  • POST请求的请求体可以包含非常多的数据,而且数据可以是任意格式。
1
xhr.open("post", "example.php", true); 
  • POST请求相比GET请求要占用更多资源。
  • 从性能方面说,发送相同数量的数据,GET请求比POST请求要快两倍。

5、XMLHttpRequest Level 2

1)FormData类型

  • FormData类型便于表单序列化,也便于创建与表单类似格式的数据然后通过XHR发送。
1
2
let data = new FormData(); 
data.append("name", "Nicholas");
  • append()方法接收两个参数:键和值,相当于表单字段名称和该字段的值。
  • 通过直接给FormData构造函数传入一个表单元素,也可以将表单中的数据作为键/值对填充进去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let data = new FormData(document.forms[0]);
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("post", "postexample.php", true);
let form = document.getElementById("user-info");
xhr.send(new FormData(form));

2)超时

  • XHR对象有一个timeout属性,用于表示发送请求后等待多少毫秒,如果响应不成功就中断请求。
  • 当超时后,XHR对象就会触发timeout事件,调用ontimeout事件处理程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
下面这个例子演示了使用timeout设置超时。给timeout设置1000 毫秒意味着,如果请求没有在1秒钟内返回则会中断。此时则会触发ont imeout事件处理程序,readyState 仍然会变成4,因此也会调用onreadystatechange事件处理程序。不过,如果在超时之后访问status属性则会发生错误。为做好防护,可以把检查status属性的代码封装在try/catch语句中。
*/
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
try {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
} catch (ex) {
// 假设由 ontimeout 处理
}
}
};
xhr.open("get", "timeout.php", true);
xhr.timeout = 1000; // 设置 1 秒超时
xhr.ontimeout = function() {
alert("Request did not return in a second.");
};
xhr.send(null);

3)overrideMineType()方法

  • overrideMineType()方法用于重写XHR响应的MIME类型
  • 假设服务器实际发送了XML数据,但响应头设置的MIME类型是text/plain。结果就会导致虽然数据是XML,但responseXML属性值是null。此时调用overrideMimeType()可以保证将响应当成XML而不是纯文本来处理。
1
2
3
4
let xhr = new XMLHttpRequest(); 
xhr.open("get", "text.php", true);
xhr.overrideMimeType("text/xml");
xhr.send(null);

二、进度事件

  • 每次请求都会首先触发loadstart事件,之后是一个或多个progress事件,接着是error、abort或load中的一个,最后以loadend事件结束。