中断一个 fetch 请求,主要使用 AbortController
实现。javascript
目前,浏览器端原生获取数据,发请求的主要是 XMLHttpRequest
和 fetch
,XMLHttpRequest
做为元老级的存在, fetch
是在 ES6 中推出的更现代的 API。java
XMLHttpRequest
自己是支持请求中断的(abort),如下是 XHR 中断的示例react
const xhr = new XMLHttpRequest()
xhr.method = 'GET'
xhr.url = 'https://slowmo.glitch.me/5000'
xhr.open(method, url, true)
xhr.send()
// 中断请求
abortButton.addEventListener('click', () => xhr.abort())
复制代码
fetch
设计之初是不支持中断的,开发者 2015 年在 GitHub 上提的 issue 仍是 open 状态,以致于开发者们尝试在 fetch
规范外兼容或解决这个问题,其中就包括 cancelable-promises 及其余 hack 方法。git
可是,如今有了通用的 AbortController
和 AbortSignal
API,这些 API 是由 DOM 标准规范 提供的,而不是由语言自己提供的。github
正如 DOM 规范文档中所说web
Though promises do not have a built-in aborting mechanism, many APIs using them require abort semantics. AbortController is meant to support these requirements by providing an abort() method that toggles the state of a corresponding AbortSignal object. The API which wishes to support aborting can accept an AbortSignal object, and use its state to determine how to proceed.npm
尽管 Promise 没有内置的停止机制,可是使用它们的许多 API 都须要停止语义。 AbortController 旨在经过提供能够切换相应 AbortSignal 对象状态的 abort() 方法来支持这些需求。 但愿支持停止的 API 能够接受 AbortSignal 对象,并使用其状态来肯定如何进行。json
如下是 AbortController
的基本用法promise
// 建立 AbortController 的实例
const controller = new AbortController()
const signal = controller.signal
// 监听 abort 事件,在 controller.abort() 执行后执行回调打印
signal.addEventListener('abort', () => {
console.log(signal.aborted) // true
})
// 触发中断
controller.abort()
复制代码
fetch
接受 AbortSignal
做为第二个参数的一部分。浏览器
const controller = new AbortController()
const signal = controller.signal
// API 5s 后返回相应
// https://slowmo.glitch.me/5000 5000 表明 5s 后返回相应值
fetch('https://slowmo.glitch.me/5000', { signal })
.then(r => r.json())
.then(response => console.log(response))
.catch(err => {
if (err.name === 'AbortError') {
console.log('Fetch was aborted')
} else {
console.log('Error', err)
}
})
// 在 2s 后中断请求,将触发 'AbortError'
setTimeout(() => controller.abort(), 2000)
复制代码
触发 controller.abort()
会中断 fetch
的 request 和 response。相同的 AbortSignal
(以上示例中的 signal )可用于停止多个获取请求。 AbortController
不只适用于 fetch
,能够适用到停止任意异步事件,好比能够实现一个可中断的promise。
除了 IE 之外,支持性仍是能够的
caniuse.com/#feat=abort… developer.mozilla.org/zh-CN/docs/…
www.npmjs.com/package/abo… www.npmjs.com/package/abo…