前言
金三银四,又快到了新的一年换工作的时候了,各种妖魔鬼怪的问题又出来了,比如 "如何根据手机壳颜色来动态改变手机主题颜色",虽然这个不是面试题,但是现在想想还是依然很好笑。
最近我会放几篇关于前端一些面试题,因为我主要是做Vue的,所以可能react的相关问题不多,但也会涉及。
今天先给大家说一个我曾经面试遇到过一个看似比较幼稚的问题,但实际还真是自己的知识盲区。— 如何中断一个网络请求?
背景知识
- XMLHttpRequest
我们都知道在前端进行网张请求的时候,基本上都是采用XMLHttpRequest这个对象。看一下官网中对此的简单介绍
"XMLHttpRequest 对象用于在后台与服务器交换数据。
什么是 XMLHttpRequest 对象?
XMLHttpRequest 对象用于在后台与服务器交换数据。
XMLHttpRequest 对象是开发者的梦想,因为您能够:
- 在不重新加载页面的情况下更新网页
- 在页面已加载后从服务器请求数据
- 在页面已加载后从服务器接收数据
- 在后台向服务器发送数据
所有现代的浏览器都支持 XMLHttpRequest 对象。" 出自 《w3school》
之前用 JQuery的时候 $.ajax 底层也是用的这个对象,包括现在非常流程的前端请求框架 axios web底层也是用的这个对象(并不是都是采用这个对象,axios是根据不同的运行环境采用不用的工作原理)
- fetch
简单介绍一下什么是 fetch
"Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch()
方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。
这种功能以前是使用 XMLHttpRequest
实现的。Fetch 提供了一个更理想的替代方案,可以很容易地被其他技术使用,例如 Service Workers
。Fetch 还提供了专门的逻辑空间来定义其他与 HTTP 相关的概念,例如 CORS 和 HTTP 的扩展。"出自 《MDN Web Docs》
也就是说现在前端进行网络请求有两种不同的实现方式,可以使用 XMLHttpRequest 方式 也可以 采用 Fetch的方式。
fetch现在可能用的还不是很多,基本上还是以 XMLHttpRequest为主。
好,简单介绍一下背景知识之后,我们正式开始今天的话题:如何中断一个正在发送的网络请求?
如何中断一个网络请求
上面我们介绍了在前端中两种请求网络的不同实现方式,现在我们就分别介绍这两种方式如何中断请求。
- XMLHttpRequest
XMLHttpRequest对象带了一个方法 abort() 可以实现这个效果,但现实是我们很少去用原生的这样的写法去请求网络,都是采用比较成熟的第三方框架去实现,所以我们这里着重介绍一下基于 axios 的实现方式。
基于 CancelToken方式:
const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', { cancelToken: source.token }).catch(function(thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // 处理错误 } }); axios.post('/user/12345', { name: 'new name' }, { cancelToken: source.token }) // 取消请求(message 参数是可选的) source.cancel('Operation canceled by the user.');
基于 executor函数:
const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // executor 函数接收一个 cancel 函数作为参数 cancel = c; }) }); // cancel the request cancel();
Fetch
先看一下浏览的支持情况吧
我们先使用AbortController()
构造函数创建一个控制器,
然后使用 AbortController.signal
属性获取其关联 AbortSignal
对象的引用。
当一个 fetch request 初始化,我们把 AbortSignal
作为一个选项传递到到请求对象(如下 { signal }
)。这将 signal和
controller 与这个
fetch request
相关联,然后允许我们通过调用
AbortController.abort() 中止请求,
如下第二个事件监听函数。
const controller = new AbortController(); let signal = controller.signal; const downloadBtn = document.querySelector('.download'); const abortBtn = document.querySelector('.abort'); downloadBtn.addEventListener('click', fetchVideo); abortBtn.addEventListener('click', function() { controller.abort(); console.log('Download aborted'); }); function fetchVideo() { //... fetch(url, {signal}).then(function(response) { //... }).catch(function(e) { reports.textContent = 'Download error: ' + e.message; }) }
当abort() 被调用时,这个fetch() promise reject 一个名为 AbortError 的 DOMException。
写在最后
大多数小伙伴可能都不知道发出去请求还能中断,原来我也不知道,但是后来查阅相关资料之后发现的确实是可以前端博大精深。
在一些面试中这些问题虽然平时用不到(也是有点用处的)但确是面试官非常喜欢问的知识,可能他们也不一定会,所以这里介绍给大家