iT邦幫忙

2021 iThome 鐵人賽

DAY 26
0
自我挑戰組

JavaScript 奇奇怪怪的核心觀念系列 第 26

(Day26) 使用 fetch 串接 Ajax

  • 分享至 

  • xImage
  •  

前言

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() ,比如這個範例:

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 轉換成一個實際可使用的物件, 其他方法還有:

  • json()
  • text()
  • bolb
  • arrayBuffer()
  • redirect()
  • clone()
  • error()

詳細部分可參考 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()

如何設定 fetch ?

在實做中 Ajax 行為往往不會向上面範例這麼簡單,通常還需要設定一些 headersmethods 等等的設定,若要設定這些功能會在 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 會需要手動將資料轉成字串。

fetch 搭配 async/await 範例

在實做中一定會碰到需要有順序的執行 Ajax 的狀況,而這邊也模擬一些狀況,使用 fetch 做 Ajax 串接,並搭配前幾個章節介紹的 async/awaitPromise.all() 來製作可以按順序來執行 Ajax 的程式碼:

  • 狀況一:需等 Ajax1 完成後,才執行 Ajax2

這種狀況使用 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()
  • 狀況二: 需等 Ajax1、Ajax2 完成後,才執行 Ajax3

這種狀況其實繼續使用 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()

參考文獻


上一篇
(Day25) Promise 語法糖 async/await
下一篇
(Day27) ESM 模組化拆檔
系列文
JavaScript 奇奇怪怪的核心觀念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言