認識 Fetch API

尋夢新聞LINE@每日推播熱門推薦文章,趣聞不漏接❤️

加入LINE好友

(給前端大全加星標,提升前端技能)

英文:Flavio 譯文:眾成翻譯/涯丨角

https://zcfy.cc/article/understanding-the-fetch-api

介紹 Fetch API

自從1998年發布IE5以來,瀏覽器中異步網路請求都是通過 XMLHttpRequest (XHR)。

這之後幾年,Gmail等應用大量使用這種方法,使這種方法逐漸流行,並給它一個名字:AJAX

直接使用XMLHttpRequest總是非常痛苦的,許多庫都對這種方法進行了封裝,特別地,jQuery封裝的方法如下:

  • jQuery.ajax()

  • jQuery.get()

  • jQuery.post()

這些方法內部做了許多兼容性的處理,來使這些方法在那些較老版本的瀏覽器上仍能正常工作。

Fetch API 已經作為現代瀏覽器中異步網路請求的標準方法,其使用 Promise 作為基本構造要素。

Fetch 在主流瀏覽器中都有很好的支持,除了IE。

認識 Fetch API 親子 第1張

GitHub 上有發布的polyfill https://github.com/github/fetch ,使fetch可以在任何瀏覽中使用。

使用Fetch

GET 請求中使用Fetch非常簡單,如下:

fetch('/file.json')

上面這段代碼表示,fetch 創建了一個 HTTP 請求,去本域下請求 file.json 資源。

正如你看到的,fetch函數可以在全局window作用域下使用。

現在,我們做些更有用的事,來看一看請求到的文件的內容:

fetch('./file.json')

.then(response=>response.json())

.then(data=>console.log(data))

fetch() 會返回一個 promise。然後我們用then()方法編寫處理函數來處理promise中異步返回的結果。

處理函數會接收fetch promise的返回值,這是一個 Response 對象。

我們會在下一部分看到這個對象的細節。

捕獲錯誤

既然 fetch() 返回一個promise,我們可以用promise的catch來攔截在執行這個請求和then里面回調函數中發生的任何錯誤。

fetch('./file.json')

.then(response=>{

//...

})

.catch(err=>console.error(err))

響應對象

調用fetch()所返回的響應對象包含了所有關於這個網路請求的請求和響應信息。

元數據

headers

HTTP請求的頭部信息可以通過訪問響應對象的headers屬性,如下所示:

fetch('./file.json').then(response=>{

console.log(response.headers.get('Content-Type'))

console.log(response.headers.get('Date'))

})

認識 Fetch API 親子 第2張

status

這個屬性是一個整形數字,表示HTTP響應狀態。

  • 101, 204, 205, 或 304 代表沒有響應體的狀態

  • 200 到 299 代表請求成功的狀態

  • 301, 302, 303, 307, 或 308 代表重定向的狀態

fetch('./file.json').then(response => console.log(response.status))

statusText

statusText 屬性表示響應狀態信息。如果請求成功,其值為”OK”。

fetch('./file.json').then(response => console.log(response.statusText))

url

url 表示我們請求資源的全路徑URL。

fetch('./file.json').then(response => console.log(response.url))

響應體

響應會有響應體,可以通過 text() 或者 json() 方法來拿到,這會返回一個promise對象。

fetch('./file.json')

.then(response=>response.text())

.then(body=>console.log(body))

fetch('./file.json')

.then(response=>response.json())

.then(body=>console.log(body))

認識 Fetch API 親子 第3張

相同的功能可以用 ES2017 async 函數:

;(async()=>{

constresponse=awaitfetch('./file.json')

constdata=awaitresponse.json()

console.log(data)

})()

請求對象

請求對象表示請求一個資源請求,它通常通過 new Request() API創建。

例如:

const req = new Request('/api/todos')

請求對象提供了幾個只讀的屬性來檢查資源請求的細節,包括

  • method: 請求方法 (GET, POST, 等)

  • url: 請求的URL

  • headers: 請求的頭部信息對象

  • referrer: 請求的網站來路

  • cache: 請求的緩存模式(例如:default, reload, no-cache).

並且提供了一些方法,如:json(), text() 和 formData() 來 處理請求體。

全部的API可以查看https://developer.mozilla.org/docs/Web/API/Request

請求頭

設置 HTTP 請求頭是一個基本的功能,fetch通過Headers對象來讓我們操作請求頭:

constheaders=newHeaders()

headers.append('Content-Type','application/json')

或者更簡單可以這樣:

constheaders=newHeaders({

'Content-Type':'application/json'

})

為了把headers加到請求中,我們用Request對象,把它添加到fetch()函數的參數中,代替傳URL參數。

代替下面的代碼:

fetch('./file.json')

我們這樣做

constrequest=newRequest('./file.json',{

headers:newHeaders({

'Content-Type':'application/json'

})

})

fetch(request)

Headers 對象沒有被限制設置值,我們也可以查詢它:

headers.has('Content-Type')

headers.get('Content-Type')

並且我們可以刪除之前設置的header:

headers.delete('X-My-Custom-Header')

POST請求

Fetch 也可以用其它的 HTTP 方法,如:POST, PUT, DELETE 或者 OPTIONS。

在method屬性中指定請求的方法,可以在請求頭和請求體中添加額外的參數:

這是一個POST請求的例子:

constoptions={

method:'post',

headers:{

'Content-type':'application/x-www-form-urlencoded; charset=UTF-8'

},

body:'foo=bar&test=1'

}

fetch(url,options).catch(err=>{

console.error('Request failed',err)

})

Fetch 弊端

雖然fetch比XHR有極大的提高,特別是它在Service Worker中的集成,但是 Fetch 現在還 沒有方法中止一個請求 。而且用 Fetch 不能監測上傳進度

如果在你的應用中需要這些功能, Axios 庫可以是個不錯的選擇。

如何取消fetch請求

在fetch剛出現的幾年,並沒有一個方法來取消已經發出的請求。

現在我們可以這樣做了,多虧了AbortController 和 AbortSignal,這是個通用的API 來通知 中止 事件。

你可以通過添加一個signal參數來整合這些API:

constcontroller=newAbortController()

constsignal=controller.signal

fetch('./file.json',{signal})

你可以設置一個超時,在請求發出後5秒後,來取消請求:

setTimeout(() => controller.abort(), 5 * 1000)

很方便地,如果fetch已經返回,調用abort()函數不會導致錯誤。

當取消信號發生,fetch會拋出一個DOMException,異常的name屬性值為”AbortError”,可以在promise的catch中捕獲這個異常:

fetch('./file.json',{signal})

.then(response=>response.text())

.then(text=>console.log(text))

.catch(err=>{

if(err.name==='AbortError'){

console.error('Fetch aborted')

}else{

console.error('Another error',err)

}

})

推薦閱讀

(點擊標題可跳轉閱讀)

深入淺出Fetch API

前端進擊的巨人(1):執行上下文與執行棧,變量對象

三個值得期待的 JavaScript 新特性!

覺得本文對你有幫助?請分享給更多人

關注「前端大全」加星標,提升前端技能

認識 Fetch API 親子 第4張

喜歡就點一下「好看」唄~