用 ES6 語法串接 API - Fetch


Posted by Calon on 2022-05-10

在 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),
})

參考資料

#javascript #ES6







Related Posts

實作一個 ChatGPT 打字機效果 request - EventSource

實作一個 ChatGPT 打字機效果 request - EventSource

JavaScript 五四三 Ep.05 Array.prototype.find()

JavaScript 五四三 Ep.05 Array.prototype.find()

每日心得筆記 2020-06-24(三)

每日心得筆記 2020-06-24(三)


Comments