JavaScript | Fetch 讓 ES6 擁有一對翅膀-基礎教學
前言
「使用 Jquery 框架中的 Ajax 就能輕鬆做到了!」
莫約幾年前,在 ES6
已推出卻又還沒有普及的時候,如果有人提到:「如何用 JavaScript
向 server
請求資料?」,一定會有人這麼留言回答。
沒錯! $.ajax
幾乎是最簡單又容易上手的請求方式了,不只在底層做了許多處理,也不必再向原生 JavaScript
中又臭又長的 XMLHttpRequest()
請求物件低頭,甚至還幫忙處理了同步執行的模式,使用起來就像這樣:
$.ajax({
type: 'get',
url: 'https://httpbin.org/get',
success: result => {
console.log(result)
}
})
看起來很棒!對吧?但那都是幾年前了。
模組化(NPM & Module)
近年前端工程在網頁上越來越吃重,投入前端框架的開發者(Developer)變多,讓以前一黨獨大的 JQuery
開始被多個許多小功能的框架給取代,因為 JQuery
擁有太多網站中用不到的 function
,但他們依然會被載入到網頁中。
面臨上述供給大於需求的情況,許多人便紛紛選擇只擁有自己需要功能的小框架,減少在 Client
端載入過多多餘的程式碼。
這些趨勢間接讓撰寫原生 JavaScript
的人直線增長,從 ES6
開始出現的 Promise
、 Class
許多新原生的語法出現,終於有一天, XMLHttpRequest()
請求開始走入歷史了(或是根本沒人認識他XD)…
Fetch
Fetch
是 ES6
的新語法,主要是搭配 Promise
(Promise 的基本用法)來執行請求網站和請求後獲取 Response
的處理方式。
以下範例的請求都會從 httpbin.org 這個網站裡挑選,它提供了各種不同的請求方式,在練習時是個很棒的工具。
GET
GET
是請求中最基本的類型,在 Fetch
中預設的請求類型也是 GET
用起來就像下方:
fetch('https://httpbin.org/get')
.then((response) => {
console.log(response)
return response.json()
//return response.text()
}).then((myJson) => {
console.log(myJson)
})
Fetch
接收了一個 url
作參數,並用 then
接收此次請求的相關資訊:
資訊內包含了請求的 url
和用來判斷請求是否成功的 status
狀態等,在 response
中有兩個內建函式可以用來得到請求回傳的資料。
一個是上方 then
中 return
使用的 .json()
,能夠將回傳的資料以物件的方式傳給第二個 then
接收,另一個是 .text()
,當回傳的資料無法轉換為物件時,則會將請求資料以字串方式取出。
下方為第二個 .then
在 console
中印出的 myJson
內容,以及當使用 .text()
時的資料模樣:
POST
與 GET
不同的是,使用 POST
請求時需另外在 method
屬性內指定 POST
方式,且多了 body
屬性指定要送出的資料:
fetch('https://httpbin.org/post', {
method: 'POST',
body: JSON.stringify(
{
name: 'GQSM',
age: 25
}
)
}).then((response) => {
return response.json()
}).then((myJson)=>{
console.log(myJson)
})
Fetch
在未指定請求方式的情況下都是使用 GET
,但是 GET
本身無法在請求中藉由 body
送出資料,因此在有 body
屬性的狀態下,未替 method
指定為 POST
或其他可帶 body
的請求方式時,會出現以下錯誤:
需要注意的是, body
內的資料需使用 JSON.stringify
將物件轉換成字串型態,否則 server
端會無法正確取得資料,以下是 data
送進 server
的差別:
未使用 JSON.stringify
的請求會直接將物件強制轉為字串,變成 [object Object]
送至 server
,使用了正確轉換的請求在 server
端則是能接收到正確的內容。
請求失敗
在 Fetch
中,請求失敗時不會有像 $.ajax
中有 error
可以直接捕捉,取而代之的是要以 response
的 status
的屬性值判斷,當 status
的值不等於 200
時,將在 .then
中使用 throw
創建一個錯誤,並由 .catch
接收錯誤內容處理:
fetch('https://httpbin.org/status/500', {
}).then((response) => {
if(response.status !== 200)
throw new Error(response.status)
return response.json()
}).then((myJson) => {
console.log(myJson)
}).catch((error) => {
console.log(`錯誤代碼為${error}`)
})
本文介紹了 Fetch
的基本用法及請求錯誤時的捕捉方式,雖然寫起來未必比 $ajax
還要簡單,但是從此以後也多了不需掛載 JQuery
轉為使用原生請求的選擇,唯一需要考量的是 Fetch
和 Promise
在瀏覽器上的支援度還太低,當換到 IE
時便完全無法使用。
不過就如前言所說的,目前投入前端框架的開發者有太多了,將來也會介紹筆者目前對處理請求使用的框架 axios
, axios
的使用方式和 Fetch
大同小異,在不考慮 Promise
的情況下,大幅度提高了瀏覽器的支援性,至少在 IE11
上也變得能夠使用,有興趣可以先至 GitHub 上查看文檔。
如果以上內容有任何問題,或是不理解的地方,都歡迎留言告訴我,謝謝大家!
參考文章