1、XMLHttpRequest对象
是什么
把 Ajax 推到历史舞台上的关键技术是 XMLHttpRequest(XHR)对象。这个对象最早由微软发明, 然后被其他浏览器所借鉴。xhr 对象支持发送同步请求、异步请求
怎么用
xhr使用较为复杂,axios对其进行了封装
// 1、创建xhr对象
let xhr = new XMLHttpRequest();
// 2、设置请求参数
// open的第三个参数用于控制是否异步,默认true,异步
xhr.open("get", "https://www.yuque.com/", true);
// 3、监听状态变化
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
// 4、设置请求头
xhr.setRequestHeader("MyHeader", "MyValue");
// 5、请求发出去
xhr.send();
readyState是什么?
xhr.readyState 表示当前处在请求/响应过程的哪个阶段,这个属性有如下可能的值
0:未初始化(Uninitialized)。尚未调用 open()方法
1:已打开(Open)。已调用 open()方法,尚未调用 send()方法
2:已发送(Sent)。已调用 send()方法,尚未收到响应
3:接收中(Receiving)。已经收到部分响应
4:完成(Complete)。已经收到所有响应,可以使用了
如何中断请求?
xhr.abort(),调用这个方法后,XHR 对象会停止触发事件,并阻止访问这个对象上任何与响应相关的属性
进度事件
Progress Events 下有6 个进度相关的事件:
loadstart:在接收到响应的第一个字节时触发
progress:在接收响应期间反复触发
error:在请求出错时触发
abort:在调用 abort() 终止连接时触发
load:在成功接收完响应时触发
loadend:在通信完成时,且在 error、abort 或 load 之后触发
每次请求都会首先触发 loadstart 事件,之后是一个或多个 progress 事件,接着是 error、abort 或 load 中的一个,最后以 loadend 事件结束
重点介绍下 load、progress 事件
load 事件: 只要是从服务器收到响应,无论状态码是什么,都会触发 load 事件
let xhr = new XMLHttpRequest();
xhr.onload = function () {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
};
xhr.open("get", "altevents.php", true);
xhr.send(null);
progress 事件: 在浏览器接收数据期间,这个事件会被持续触发,其回调的 event 对象中有两个关键属性---loaded、total,前者表示浏览器当前接收到的数据大小,后者表示本次请求的总数据大小
实际应用:文件下载,如果后端无法提供进度字段,前端可以用以上属性模拟下载进度
xhr.onprogress = function (event) {
let loaded = event.loaded;
let total = event.total;
if (event.lengthComputable) {
console.log("下载进度:" + (loaded / total) * 100 + "%");
}
};
2、fetch函数
是什么
fetch 函数能够执行 XMLHttpRequest 对象的所有任务,但更容易使用,接口也更现代化。与xhr的一大不同是,xhr 可以选择同步还是异步请求,而 fetch 函数 只能发异步请求
怎么用
浏览器环境下,直接调用 fetch 函数,传入URL、配置对象等,返回值是一个 Promise
fetch('"https://www.yuque.com/"', {
// 配置对象,可以配置请求头、请求方式、请求体等等
method: "get",
})
.then(async (res) => {
let data = await res.text();
})
.catch((err) => {
console.log(err);
});
如何中断请求?
用 AbortController 对象对中断请求。调用 AbortController. abort() 会中断所有网络传输,特别适合希望停止传输大型负载的情况
// 中断请求
let abortController = new AbortController();
fetch("wikipedia.zip", { signal: abortController.signal })
.catch(() =>console.log("aborted!"));
// 10 毫秒后中断请求
setTimeout(() => abortController.abort(), 10);
3、sendBeacon 函数
navigator 对象增加了一个 sendBeacon() 方法,主要用于在页面卸载(如关闭页面、跳转页面)时,异步地向服务器发送少量数据
它和 xhr 相比的优势:如果 xhr 请求是同步的,会阻塞页面卸载,导致用户体验变差;如果 xhr 是异步的,在页面卸载时请求可能还未发出去就被终止,从而无法保证数据能成功发送到服务器
这个简单的方法接收一个 URL 和一个数据有效载荷参数,并会发送一个 POST 请求
navigator.sendBeacon(
"https://example.com/analytics-reporting-url",
'{foo: "bar"}'
);
特性:
sendBeacon() 并不是只能在页面生命周期末尾使用,而是任何时候都可以使用
调用 sendBeacon() 后,浏览器会把请求添加到一个内部的请求队列,因此它异步、不阻塞主线程
浏览器保证在原始页面已经关闭的情况下也会发送请求
状态码、超时和其他网络原因造成的失败完全是不透明的,不能通过编程方式处理