(Day26) 使用 fetch 串接 Ajax
前言
fetch
是 JavaScript ES6 新增的用來執行 Ajax 行為的方法,相比舊版的 XMLHttprequest
不論是閱讀程式碼、或是實際開發都方便不少,而 fetch
其實就是使用 Promise
開發的方法,因此 fetch
語法和 Promise
寫法非常類似,同時可以使用到上個章節提到的 async/await
。
本篇會使用 https://randomuser.me/
來做 ajax 範例。
fetch 基本介紹
要使用 fetch
直接使用 fetch()
並帶上網址便可執行 Ajax 行為,上面有提到 fetch
其實就是使用 Promise
開發的方法,因此當 fetch
的 Ajax 成功後,會使用和 Promise
相同使用 .then()
來執行成功的程式碼,失敗則是使用 .catch()
,比如這個範例:
1 | fetch('https://randomuser.me/api/') |
當 fetch
成功後,會回傳 ReadableStream
物件,這時會使用不同的方法取得對應資料,上面範例就使用 json()
來將 ReadableStream
轉換成一個實際可使用的物件, 其他方法還有:
- json()
- text()
- bolb()
- arrayBuffer()
- redirect()
- clone()
- error()
詳細部分可參考 MDN 文件介紹:https://developer.mozilla.org/zh-TW/docs/Web/API/Response
上面也有提到 fetch
也可以搭配 async/await
,以上面範例來製作 async/await
版本:
1 | async function useAjax() { |
如何設定 fetch
在實做中 Ajax 行為往往不會向上面範例這麼簡單,通常還需要設定一些 headers
、 methods
等等的設定,若要設定這些功能會在 fetch()
中第二個參數做詳細設定,而第二個參數必需寫成物件,比如這個範例:
1 | fetch('http://httpbin.org/post', { |
值得一提的是,使用 post
行為時 ,我們通常會帶上一些資料給後端,和其他包裝好的 Ajax 框架不同, fetch
會需要手動將資料轉成字串。
fetch 搭配 async/await 範例
在實做中一定會碰到需要有順序的執行 Ajax 的狀況,而這邊也模擬一些狀況,使用 fetch
做 Ajax 串接,並搭配前幾個章節介紹的 async/await
、 Promise.all()
來製作可以按順序來執行 Ajax 的程式碼:
- 狀況一:需等 Ajax1 完成後,才執行 Ajax2
這種狀況使用async/await
或是 原生Promise
鏈式寫法都能達成,這邊以async/await
為範例:
1
2
3
4
5
6
7
8
9
10
11
12
13async function useAjax() {
try {
const ajax1 = await fetch('https://randomuser.me/api/')
const data1 = await ajax1.json()
console.log('data1', data1)
const ajax2 = await fetch('https://randomuser.me/api/')
const data2 = await ajax2.json();
console.log('data2', data2)
} catch (error) {
console.log('錯誤:', err)
}
}
useAjax() - 狀況二: 需等 Ajax1、Ajax2 完成後,才執行 Ajax3
這種狀況其實繼續使用async/await
來寫也可以達成,不過會變成:
執行 Ajax1 ⇒ Ajax1 完成 ⇒ 執行 Ajax2 ⇒ Ajax2 完成 ⇒ 執行 Ajax3
這樣就會浪費較多時間再等待 Ajax 回傳,所以比較好的方法就是使用Promise.all()
搭配async/await
,或是單純Promise.all()
加上Promise
鏈式寫法,這邊以Promise.all()
搭配async/await
為範例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17async function useAjax() {
try {
const ajax1 = fetch('https://randomuser.me/api/')
const ajax2 = fetch('https://randomuser.me/api/')
const [res1, res2] = await Promise.all([ajax1, ajax2])
const data1 = await res1.json()
const data2 = await res2.json()
console.log('data1', data1)
console.log('data2', data2)
const ajax3 = await fetch('https://randomuser.me/api/')
const data3 = await ajax3.json()
console.log('data3', data3)
} catch(error) {
console.log('錯誤:', err)
}
}
useAjax()
參考文獻
- 鐵人賽:ES6 原生 Fetch 遠端資料方法
- MDN 文件 - fetch