在 ES6 以前如果想要用原生 JavaScript 串接 API 的話可以使用 XMLHttpRequest
,但是寫起來很長又不是那麼的直覺(以下使用 https://randomuser.me/ 提供的 API 來示範):
// 宣告一個 XMLHttpRequest 物件
const xhr = new XMLHttpRequest();
// 定義請求方式
xhr.open('GET', 'https://randomuser.me/api/');
// 送出請求
xhr.send(null);
// 請求成功時
xhr.onload = () => {
if (xhr.status === 200) {
const data = JSON.parse(xhr.response);
}
}
// 請求失敗時
xhr.onerror = () => {
alert('請求失敗');
}
除了寫起來很麻煩外,如果有其他請求的需要就必須新建多個 XMLHttpRequest 實體,所以通常都會使用包裝好的框架 jQeury 的 $.ajax
,而在 ES6 有了 Promise
後也有 Axios 套件可以使用,讓 AJAX 請求的程式碼更容易閱讀。
現在除了比較舊一點的線上課程、教學外,應該不太容易見到 XMLHttpRequest
的身影了。
Fetch
在 ES6 新增了 Promise
的同時,也新增了 fetch
語法,主要是搭配 Promise
來處理 AJAX。
GET
GET 是最常見到了請求類型,在 Fetch
中預設也是使用 GET:
fetch('https://randomuser.me/api/')
.then((res) => {
console.log(res);
})
.catch((err) => {
console.dir(err);
});
因為 Fetch
是使用 Promise
來做回應:
then
接收請求回應catch
接收錯誤回應
下圖為請求成功後回傳的內容:
當請求成功後 Fetch
會回傳一個 ReadableStream
物件,這時還無法直接取得內容,我們可以根據需求使用以下方法來取得資料(文件):
- json()
- text()
- arrayBuffer()
- blob()
- formData()
下圖為對回傳結果 res
使用 json()
後的內容:
會發現是一個 Promise
物件,所以我們要在將 res.json()
回傳並用 then
去做接收:
fetch('https://randomuser.me/api/')
.then((res) => {
return res.json();
})
.catch((err) => {
console.dir(err);
})
.then((res) => {
console.log(res);
});
這裡要注意如果 HTTP 狀態碼是 400 或是 500 的錯誤,Fetch
並不會把它歸類成錯誤(reject),而是會用 then
(reslove)去做接收,但是物件中 ok 的值會是 false
。
只有在網路錯誤或是請求中斷時才會用 catch
來接收錯誤回應。
所以我們可以用 ok 或是 status 的值來做判斷,這邊使用 ok 來做範例:
fetch('https://randomuser.me/api/')
.then((res) => {
if (res.ok) {
return res.json();
}
})
.catch((err) => {
console.dir(err);
})
.then((res) => {
console.log(res);
});
POST
在使用 POST 時我們需要另外在 method 去做設定(POST 方法使用 httpbin.org 來作為範例):
fetch('https://httpbin.org/post', {
method: 'POST',
})
而將需要傳送的資料放在 body 屬性,並且要注意傳送的內容只能是字串:
const data = {
name: 'Calon',
age: 24,
};
fetch('https://httpbin.org/post', {
method: 'POST',
// 設定傳送的資料格式描述
headers: {
'Content-Type': 'application/json',
},
// 將要傳送的資料用 JSON.stringify() 轉為字串
body: JSON.stringify(data),
})
.then((res) => {
return res.json();
})
.then((res) => {
console.log(res);
});
如果需要帶上 token,也是在 headers 裡面設定:
fetch('https://httpbin.org/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': '要帶入的 token',
},
body: JSON.stringify(data),
})