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…

相關文章
相關標籤/搜索