尋夢新聞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。
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'))})
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))
相同的功能可以用 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.signalfetch('./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)}})
推薦閱讀
(點擊標題可跳轉閱讀)
覺得本文對你有幫助?請分享給更多人
關注「前端大全」加星標,提升前端技能
喜歡就點一下「好看」唄~