ID: 符合预期的CoyPan
CoyPan,BAT某厂符合预期的FE,正努力成为一名出色的工程师
写在前面
在网页中,Ajax和Fetch是最常用的发起网络请求的两种方式。在面试中,关于这两者的区别也会被提及。你也许听说过这么一个说法,Ajax是可以取消的,Fetch是不可以取消的。真的是这样吗?
取消Ajax
使用ajax发起一个网络请求的代码大致如下:
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onreadystatechange = function(){};
xhr.send();
想要中断这个ajax请求,直接调用
xhr.abort()
取消fetch
使用fetch发起一个网络请求的代码大致如下:
fetch(url)
.then(r => r.json())
.then(response => {
})
.catch(err => {
console.error("Error in fetching!", err);
});
fetch是基于promise的,可以在页面主线程、worker等地方使用,十分的方便。
想取消一个fetch请求,可以使用AbortController
.
AbortController代表一个控制器对象,允许你在需要时中止一个或多个DOM请求。直接来看示例代码:
var controller = new AbortController();
var signal = controller.signal;
// 将signal传入fetch的第二个参数
fetch(url, { signal })
.then(function(response) {
...
}).catch(function(err) {
if (err.name === 'AbortError') {
console.log('Fetch was aborted');
} else {
console.error('Oops!', err);
}
});
setTimeout(() => {
controller.abort(); // 取消fetch请求
}, 1000);
当我们主动取消fetch时,fetch的promise 会 reject 以下错误:
new DOMException('Aborted', 'AbortError')
这个时候,会进入fecth的catch逻辑块。
当然,如果fetch已经resolve了,我们就无法取消fetch了。
AbortController 当前的兼容性如下:
polyfills如下:
写在后面
取消网络请求是一个很重要的点,特别是在页面中有大量请求,而用户切到其他页面时,适当的取消pending中的网络请求,可以减少网络资源的浪费和页面卡顿,提升用户体验。fetch,也是可以取消的。
最后,推荐一个不错的fetch库: