Fetch 实现 abort

中断一个 fetch 请求,主要使用 AbortController 实现。javascript

目前,浏览器端原生获取数据,发请求的主要是 XMLHttpRequestfetchXMLHttpRequest 做为元老级的存在, 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

可是,如今有了通用的 AbortControllerAbortSignal API,这些 API 是由 DOM 标准规范 提供的,而不是由语言自己提供的。github

什么是 AbortController?

image.png

正如 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()
复制代码

怎么使用 AbortController 中断 fetch 请求?

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/…

polyfill

www.npmjs.com/package/abo… www.npmjs.com/package/abo…

参考:

developers.google.com/web/updates… github.com/whatwg/fetc…

相关文章
相关标签/搜索