今天會承接昨天AJAX的課題,了解常用來處理AJAX的語法,Fetch,以及試試用fetch來實作GET、POST請求。
fetch基本語法
Fetch是一個全域
window
物件,用途是送出request。當請求成功,fetch就會回傳一個promise物件(狀態是fulfilled),這物件內會帶有response物件,裏面會放有我們想抓的資料。
fetch語法:
let promise = fetch(url, [options])
url是要訪問的網址
options
是一堆可選的参數,例如method、header
如果只有url,沒有[options],就會預設這個請求的HTTP請求方法是GET。
Fetch的語法結構與Promise
非常相似,同樣是用then
和catch
方法來處理成功和失敗的結果:
fetch( 你想訪問的url,{...一堆参數(可選)} )
.then((response) => {
//成功結果處理
.catch((error) => {
//錯誤結果處理
當透過fetch語法,從瀏覽器向伺服器發出GET請求後,接下來的流程可分為兩大部分。以下會用https://randomuser.me/api/
去做一個簡單示範,這個API會隨機產生一個人的資料。
階段1: fetch傳回帶有Response物件的Promise物件
fetch('https://randomuser.me/api/')
.then((response) => {
console.log(response);
.catch((error) => {
console.log(`Error: ${error}`);
我們可以從status
和ok
查看HTTP狀態。ok
是一個布林值,如果status
是200-299,它就是true
。
階段2: 從Response物件中抽取我們想抓的資料
雖然在階段一回傳了Response物件,但這不是我們想抓的資料,即是我們常常說的「回應內容主體(Response body)」,接下來我們需要使用方法來取得它。
Response有多種方法讓我們取得資料(內容主體),包括我們常常用到的.json()
:
response.json()
:把資料轉成JSON格式
response.text()
:把資料轉成text格式(變成純字串)
response.blob()
:把資料轉成Blob物件
response.formData()
:把資料轉成FormData物件
response.arrayBuffer()
:把資料轉成二進制數組
注意,只能使用一種方法來取得資料。例如我用了.json()
的方法後,不能再用另一種方法來取得資料,因為該資料已經被處理過了。
我們最常用到就是JSON格式資料,以下例子會用.json()
的方法取得資料:
fetch('https://randomuser.me/api/')
.then((response) => {
return response.json();
.then( (response) => {
console.log(response);
.catch((error) => {
console.log(`Error: ${error}`);
最後就取得資料了:
async/await
的寫法原理是一樣的,以下試試用async/await
去重寫以上例子:
let getJSON = async(url) => {
let response = await fetch(url);
let JSON = await response.json();
console.log(JSON)
getJSON('https://randomuser.me/api/')
Header
上面曾提及過,在fetch()
裏可以有兩個参數,第一個是URL,第二個是一堆参數,例如method
、header
等等。當中的header
就是Request header,即是請求表頭,它用來描述我們發出的請求,例如是請求URL、請求方法。
Header這個術語是指表頭,可以分為請求表頭(Request header)與回應表頭(Response header),它們是一堆描述這個請求或回應的資訊。我們可以用dev tool看到這些資訊:
請求表頭及回應表頭的格式是有規範,否則不能被伺服器或瀏覽器接收。以下例子示範自訂一個請求表頭:
let response = fetch('https://randomuser.me/api/',{
headers: {
Authentication: 'secret'
但基於HTTP的準確與安全性,某些設定是不能被我們定義,只能被瀏覽器定義。
當我們發出POST請求時,就需要用到fetch
裏的第二個参數,當中包括:
method (HTTP請求方法)
request body (請求主體)
當中的request body,例如可以是:
字串(用JSON.stringify轉成的字串)
FormData物件
Blob所傳送的二進制資料
以下用六角學院的API作例子,註冊後會得到一個獨立編碼(UUID),這個UUID是用來組成自己的API網址時用的,另外也會提供一個API token(後台登入驗證碼),用來驗證是否有管理員身分,並能夠管理個人專屬的後台。
這裏會示範如果新增一筆產品資料到伺服器,剛才提及uuid和token是在註冊六角學院的API系統時發給我的,我把它們放在一個個的變數裏,但這裏就不公開了。
新增一筆產品資料的API文件:
Body Parameters就是主體参數,要寫在fetch(url,{...})
的{...}
裏。
以下是完整程式碼:
const uuid = xxxxx
const token = xxxxx
const url = `https://course-ec-api.hexschool.io/api/${uuid}/admin/ec/product`
let headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": `Bearer ${token}`,
//以下是API文件中提及必寫的主體参數。而以下這個產品資料是六角學院提供的。
let body = {
"title": "Abysswalker",
"category": "T-Shirts",
"content": "Its wearer, like Artorias himself, can traverse the Abyss.",
"description": "This official Dark Souls shirt was designed by Nina Matsumoto and printed on soft 100% cotton shirts by Forward. Each one comes with a bonus sticker.",
"imageUrl": ["https://images.unsplash.com/photo-1529374255404-311a2a4f1fd9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1349&q=80"]
fetch(url, {
method: "POST",
headers: headers,
//別忘了把主體参數轉成字串,否則資料會變成[object Object],它無法被成功儲存在後台
body: JSON.stringify(body)
.then(response => response.json())
.then(json => console.log(json));
如果我新增了3次這筆資料,後台就會有3筆資料,我們也可以用"GET"的方法去查詢,六角學院提供了以下的API文件:
完整程式碼:
const url = `https://course-ec-api.hexschool.io/api/${uuid}/admin/ec/products`
let headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": `Bearer ${token}`,
fetch(url, {
method: "GET",
headers: headers,
.then( (response) => response.json())
.then( (json) => console.log(json));
結果真的會顯示3筆資料:
雖然之前已經學了Promise語法,學習Fetch時不會太吃力,但認真落手實作時才發覺也有一定的難度,而且當中有些術語,例如Body parametres、Header等等也沒有看懂,所以除了看文章,也真的是需要實作練習一下~
AJAX 完整解說系列:新增、更新、刪除(POST、PATCH、DELETE)
JAVASCRIPT.INFO
JacaScript | Fetch 讓 ES6 擁有一對翅膀-基礎教學
鐵人賽:ES6 原生 Fetch 遠端資料方法