投身烈火
Keep Walking

fetch 能做哪些 XHR(XMLHttpRequest) 不能做的事

前两天刷微博的时候刷到了紫云飞的一条微博,遂决定好好整理下,方便以后面试别人或者别人面我的时候装逼用~ ╮( ̄▽ ̄)╭

基础知识

关于 Fetch API 和 XHR 的历史、概念、方法、属性等基础知识我就不回顾了,毕竟网上一搜一大片,文档也早就有了中文翻译,想详细了解细节的就仔细读文档吧。

直奔主题

总的来说,Fetch API 和 XHR 做的事情很相似,大部分情况我们通过 XHR 就已经能够完成开发任务了。那么为什么还需要新的 Fetch API呢?个人认为 相比 XHR, Fetch API 可以做到以下三点:

Fetch API更加现代

XHR 和 Fetch API 最显著的区别就是调用方式不同。这一点大家应该都知道吧。

举个例子,下面两端代码完成的是同一功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 用 XHR 发起一个GET请求
var xhr = new XHMHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';
xhr.onload = function() {
console.log(xhr.response);
};
xhr.onerror = function() {
console.log('something wrong~ ╮( ̄▽ ̄)╭');
};
xhr.send();
// 用 Fetch 完成同样的请求
fetch(url).then(function(response) {
return response.json();
}).then(function(jsonData) {
console.log(jsonData);
}).catch(function() {
console.log('something wrong~ ╮( ̄▽ ̄)╭');
});

相比 XHR ,Fetch 结合了现代的编码模式,使用起来更简洁 ,完成工作所需的实际代码量也更少。

Fetch API更底层

其实,刚才说到的 Fetch API 并不是指仅仅一个 fetch 方法,还包括 Request、 Response、Headers、Body都一系列原生对象。对于传统的XHR而言,你必须使用它的一个实例来发出请求和处理响应。 但是通过Fetch API,我们还能够通过刚才提到的原生对象,明确的配置请求和响应。这些底层的抽象让 Fetch API 比 XHR 更灵活。

举个例子,现在要下载一个很大的 utf-8 格式的 txt 文件,我们通过流式的响应体而不是文本的形式读取,最后显示在一个div中。(为什么使用流、使用流有什么好处我就不做过多解释了……)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
document.addEventListener('DOMContentLoaded', function (e) {
var url = 'Test.txt';
var div = document.getElementById('content');
var progress = 0;
var contentLength = 0;
fetch(url).then(function(response) {
// 通过响应头获取文件大小
contentLength = response.headers.get('Content-Length');
var pump = function(reader) {
return reader.read().then(function(result) {
// 如果流中的内容读取完毕,result.done的值会变为true
if (!result.done) {
// 获取流中的数据
var chunk = result.value;
var text = '';
// 流中的数据是一串字节码,需要做转码
for (var i = 3; i < chunk.byteLength; i++) {
text += String.fromCharCode(chunk[i]);
}
// 添加到页面的div中
div.innerHTML += text;
// 还可以用流的长度显示当前进度
progress += chunk.byteLength;
console.log(((progress / contentLength) * 100) + '%');
// 开始读取下一个流
return pump(reader);
}
});
}
// 开始读取流中的信息
return pump(response.body.getReader());
})
.catch(function(error) {
console.log(error);
});
});

在上面的例子中,我们不止使用了流来下载文件,还通过响应头获取了响应的具体信息,显示了下载的进度。虽然使用XHR也能做到使用流来读取文件,不过现在应该只有IE浏览器支持。但是 Fetch API 提供了访问数据的实际字节的方法,而 XHR 的 responseText 只有文本形式,这意味着在某些场景下它的作用可能非常有限。

Fetch API更接近未来

当我们在谈论 Fetch API 时,我们在谈论的不止是这些已经胜过 XHR 的地方,更是在谈论 Fetch API未来的可能性。比如未来基于 Fetch 和 Service Worker 的缓存和请求拦截技术。由于时间关系细节就不展开了,详细的内容可以参考一下链接。

最后

虽然现在很多Fetch API 的功能还是实验性的,但是虽然现代浏览器的普及,以及诸如promise、async/await等异步语法的实现,相信不久的将来,Fetch 肯定会取代 XHR吧。到时候希望这篇文章能帮助你装逼成功,哈哈~ ╮( ̄▽ ̄)╭

好的那么由于时间不足本次的博客就到这里,如果不出意外的话,大概可能maybe也许下周五会更新吧~!能不能准时更新,就全看米娜桑点赞打赏转发安利发评论的热情啦~!

白了个白~!