fetch
是 JavaScript ES6 新增的用來執行 Ajax 行為的方法,相比舊版的 XMLHttprequest
不論是閱讀程式碼、或是實際開發都方便不少,而 fetch
其實就是使用 Promise
開發的方法,因此 fetch
語法和 Promise
寫法非常類似,同時可以使用到上個章節提到的 async/await
。
本篇會使用 https://randomuser.me/
來做 ajax 範例。
要使用 fetch
直接使用 fetch()
並帶上網址便可執行 Ajax 行為,上面有提到 fetch
其實就是使用 Promise
開發的方法,因此當 fetch
的 Ajax 成功後,會使用和 Promise
相同使用 .then()
來執行成功的程式碼,失敗則是使用 .catch()
,比如這個範例:
fetch('https://randomuser.me/api/')
.then((response) => {
// 回傳 ReadableStream 物件,可使用 .json() 等等方法,取得對應資料。
return response.json()
}).then((data) => {
console.log(data)
}).catch((err) => {
console.log('錯誤:', err)
})
當 fetch
成功後,會回傳 ReadableStream
物件,這時會使用不同的方法取得對應資料,上面範例就使用 json()
來將 ReadableStream
轉換成一個實際可使用的物件, 其他方法還有:
詳細部分可參考 MDN 文件介紹:https://developer.mozilla.org/zh-TW/docs/Web/API/Response
上面也有提到 fetch
也可以搭配 async/await
,以上面範例來製作 async/await
版本:
async function useAjax() {
try{
const ajax = await fetch('https://randomuser.me/api/');
const data = await ajax.json();
console.log(data)
} catch(error) {
console.log('錯誤:', err)
}
}
useAjax()
在實做中 Ajax 行為往往不會向上面範例這麼簡單,通常還需要設定一些 headers
、 methods
等等的設定,若要設定這些功能會在 fetch()
中第二個參數做詳細設定,而第二個參數必需寫成物件,比如這個範例:
fetch('http://httpbin.org/post', {
// Ajax 行為改為 Post
method: 'POST',
// headers 加入 json 格式
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
test: '123',
})
})
.then((response) => {
return response.json()
}).then((Data) => {
console.log(Data)
}).catch((err) => {
console.log('錯誤:', err)
})
值得一提的是,使用 post
行為時 ,我們通常會帶上一些資料給後端,和其他包裝好的 Ajax 框架不同, fetch
會需要手動將資料轉成字串。
在實做中一定會碰到需要有順序的執行 Ajax 的狀況,而這邊也模擬一些狀況,使用 fetch
做 Ajax 串接,並搭配前幾個章節介紹的 async/await
、 Promise.all()
來製作可以按順序來執行 Ajax 的程式碼:
這種狀況使用 async/await
或是 原生 Promise
鏈式寫法都能達成,這邊以 async/await
為範例:
async 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()
這種狀況其實繼續使用 async/await
來寫也可以達成,不過會變成:
執行 Ajax1 ⇒ Ajax1 完成 ⇒ 執行 Ajax2 ⇒ Ajax2 完成 ⇒ 執行 Ajax3
這樣就會浪費較多時間再等待 Ajax 回傳,所以比較好的方法就是使用 Promise.all()
搭配 async/await
,或是單純 Promise.all()
加上 Promise
鏈式寫法,這邊以 Promise.all()
搭配 async/await
為範例。
async 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()