前端领域如何实现请求中断( 四 )

这里我们同样提供CacheUtils.clearCache函数来应对需要手动清除未完成请求的应用场景,使用方式与上一小节思路相同,这里就不再重复多讲 。
3、Fetch API
作为浏览器原生提供的XHR构造函数的理想替代方案,新增的Fetch API为我们提供了Request和Response(以及其他与网络请求有关的)对象的通用定义,一个Request对象表示一个资源请求,通常包含一些初始数据和正文内容,例如资源请求路径、请求方式、请求主体等,而一个Response对象则表示对一次请求的响应数据 。
同时Fetch API还为我们提供了一个全局的fetch方法,通过该方法我们可以更加简单合理地跨网络异步获取资源 。fetch方法不仅原生支持Promise的链式操作,同时还支持直接传入Request对象来发送请求,增加了很强的灵活性 。
到目前为止,Fetch API的支持程度如下图:

前端领域如何实现请求中断

文章插图
 
不难看出IE浏览器下的兼容性不容乐观,但是作为一名有追求的前端开发人员,当然不会止步于此 。一番探索之后,发现可以通过isomorphic-fetch或者whatwg-fetch这两个第三方依赖来解决兼容性问题:
复制// 安装依赖npm install --save whatwg-fetch// 引入依赖import {fetch as fetchPolyfill} from 'whatwg-fetch';1.2.3.4.接下来同样先抛出一个基础示例:
复制const url = 'http://www.some-domain.com/path/to/example';const initData = https://www.isolves.com/it/cxkf/qd/2022-01-29/{method: 'POST',body: JSON.stringify({key: value}),headers: {'Content-Type': 'application/json; charset=UTF-8',},cache: 'no-cache',credentials: 'same-origin',mode: 'cors',redirect: 'follow',referrer: 'no-referrer',};fetch(url, initData).then(response => response.json()).then(data => console.log(data));// 也可以直接通过 Request 构造函数来初始化请求数据// Request 构造函数接收两个参数// 第一个参数表示需要获取的资源 URL 路径或者另一个嵌套的 Request 实例// 第二个可选参数表示需要被包含到请求中的各种自定义选项const request = new Request(url, initData);fetch(request).then(response => response.json()).then(data => console.log(data));1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.可以看到,相比于传统的XHR方式而言,fetch函数的使用方式更加简洁友好,易用性更强,同时还为我们提供了多种入参的形式使得程序功能变得更加的灵活可扩展 。
那么回到本文的主题,上文中提到,在XHR实例中可以通过abort方法来取消请求,在Axios中可以通过CancelToken构造函数的参数来获得取消函数,从而通过取消函数来取消请求 。
但是很遗憾的是,在Fetch API中,并没有自带的取消请求的API供我们调用 。不过令人愉悦的是,除了IE浏览器外,其他浏览器已经为Abort API添加了实验性支持,Abort API允许对XHR和fetch这样的请求操作在未完成时进行终止,那么接下来对Abort API做一下简要的介绍 。
在Abort API的相关概念中主要包含了AbortController和AbortSignal两大接口:
  • AbortController:表示一个控制器对象,该对象拥有一个只读属性signal和一个方法abort 。signal属性表示一个AbortSignal实例,当我们需要取消某一个请求时,需要将该signal属性所对应的AbortSignal实例与请求进行关联,然后通过控制器对象提供的abort方法来取消请求;
  • AbortSignal:表示一个信号对象,作为控制器对象和请求之间通信的桥梁,允许我们通过控制器对象来对请求进行取消操作 。该对象拥有一个只读属性aborted和一个方法onabort,aborted属性体现为一个布尔值,表示与之通信的请求是否已经被终止,而onabort方法会在控制器对象终止该请求时调用 。
通过以上两个接口,我们尝试封装一个简单加强版的可取消的fetch工具函数:
复制const abortableFetch = (url, initData) => {// 实例化控制器对象const abortController = new AbortController();// 获取信号对象const signal = abortController.signal;return {// 注意这里需要将 signal 信号对象与请求进行关联,关联之后才能通过 abortController.abort 方法取消请求ready: fetch(url, {...initData, signal}).then(response => response.json()),// 暴露 cancel 方法,用于在外层手动取消请求cancel: () => abortController.abort(),};};1.2.3.4.5.6.7.8.9.10.11.12.并将其应用到之前的基础示例中:
复制const url = 'http://www.some-domain.com/path/to/example';const initData = https://www.isolves.com/it/cxkf/qd/2022-01-29/{method: 'POST',body: JSON.stringify({key: value}),headers: {'Content-Type': 'application/json; charset=UTF-8',},cache: 'no-cache',credentials: 'same-origin',mode: 'cors',redirect: 'follow',referrer: 'no-referrer',};const {ready, cancel} = abortableFetch(url, initData);ready.then(response => console.log(response)).catch(err => {if (err.name === 'AbortError') {console.log('请求已被终止');}});// 手动取消请求cancel();1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.


推荐阅读