前端基礎

-

前端必學 - 甚麼是 API?前端如何串接 API?

this.web

對於剛接觸的新手來說,API 是一個蠻難懂的概念。但其實它觀念蠻簡單的,前端在獲取資料時,API 通常是一個網址,前端可以透過這個網址來獲取後端送來的資料。

舉個例子,假設你現在在蝦皮買了一件衣服,要到超商取貨,超商就是一個 API。

在這個例子我們可以看三個部分,"你""超商""店家發來的貨":

  1. 你: 前端
  2. 超商: API
  3. 發貨的店家: 後端、伺服器
api

換句話說,後端會發送資料到 API,前端可以利用 API 來獲取後端送過來的資料,這就是串接 API。

所以 API 就像一個可以取得各種資料的窗口。

有了基本概念之後,我們就可以來更深入的看看 API

甚麼是 API?

API 的全名是 「應用程式介面 Application Programming Interface」。

它允許不同的應用程式之間,以規範好的方式進行溝通和互動,即使他們是用不同的語言。就比如前端和後端可以利用 API 來溝通、傳資料。

而規範的方式是可以自訂的,比如後端可以決定前端要傳什麼參數才能取得特定的資料。

為甚麼要使用 API?

有了 API 可以大大降低開發人員的負擔,用很常見的例子來說,大部分的電商網站都提供線上刷卡付款,正是因為他們串接了金流公司提供的 API,這樣他們就不需要自行開發一個結帳系統。

在舉一個例子,我們在寫 JS 時的 setIntervalsetTimeout 等都是瀏覽器提供的 API,只要我們遵循它的使用方法,就可以很方便的計時,而不用自己寫一個計時功能的函數,這也是一種 API。

還有最近很流行的 open AI 也有提供 API,讓開發人員可以在自己的應用程式開發想要的 AI 功能,例如客服聊天機器人。

所以說,API 的好處有:

  1. 促進程式整合:API 允許不同的程式或服務彼此溝通和互動。這使得系統間的整合變得更容易。就像前面說的購物支付系統。
  2. 提高效率和速度:透過使用 API,你可以利用現有的功能和資源,而不需要重新發明輪子。這樣可以節省開發時間和成本。
  3. 擴充功能和彈性:你可以利用其他系統的 API,將它們的功能放到你的應用程式中,就像前面說的 AI 機器人。

前端如何串 API

前端串 API 的方式有很多,也有很多函式庫是在幫開發者更好的串 API,今天就帶你了解原生 JS 的兩種串 API 的方式,分別為:

  1. 傳統古老的 AJAX
  2. 後來更新的 Fetch

用傳統的 AJAX 串接 API

相信很多前端新手再找教學的時候,很常看到 AJAX 這個名詞,其實 AJAX 就是串接 API 的其中一種方法。

在正式進入 AJAX 之前,我想先來講講 AJAX 是什麼。在以前沒有 ajax 技術時,若要獲得資料或是傳送資料給後端,網頁需要向後端發送請求,然後等待後端回應,回應後需要重新載入整個頁面來完成資料的傳遞,這對於用戶體驗很不好。

AJAX

而有了 ajax,我們就不需要重新載入整個頁面,因為他用到了非同步的概念,將請求和回應的部分交給瀏覽器去非同步處理JS 只負責響應結束後,執行指定的回調函數,所以在很多地方都能大大提升用戶的體驗。

AJAX2

所以 AJAX 是什麼

ajax 是一個技術,全名叫做 Asynchronous JavaScript and XML,直接翻譯就叫做 "非同步的 JS 和 XML"
XML 是一種用來儲存資料的標記語言,和 JSON 的功能類似,只不過現在更常使用 JSON 格式來儲存資料。因為和 XML 相比,JSON 更簡潔和易於讀寫。

使用 AJAX 串接 API

在 JS 中有提供一個內建的 XMLHttpRequest 物件來時做 ajax,使用方式如下

// 建立 XMLHttpRequest 物件
const xhr = new XMLHttpRequest();

// 監聽是否有回傳資料
xhr.addEventListener('readystatechange', () => {
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 請求完成且成功
    const response = xhr.responseText;
    // 處理伺服器的響應
    console.log(response);
  }
});

// 用 open() 設置發送請求的方法
xhr.open('GET', 'http://example.com/api/data', true);
// 用 send() 發送請求
xhr.send();

readyState 代表目前的請求狀態,分成四種

  • 0: 還沒開始
  • 1: 讀取中
  • 2: 已讀取
  • 3: 資訊交換中
  • 4: 完成

xhr.status 是 HTTP 的狀態碼,200 是成功的意思,常用的還有:

常用的 HTTP 狀態碼參考:

1xx 訊息回應

  • 100 Continue:客戶端應繼續其請求

2xx 成功

  • 200 OK:請求成功,常用於 GET 和 POST 請求
  • 201 Created:請求已經被實現,而且有一個新的資源已經依據請求的需要而建立
  • 204 No Content:伺服器成功處理了請求,但沒有返回任何內容

3xx 重新導向

  • 301 Moved Permanently:請求的網頁已永久移動到新位置
  • 302 Found:請求的網頁臨時重新導向到另一個位置
  • 304 Not Modified:自從上次請求後,請求的網頁未修改過

4xx 客戶端錯誤

  • 400 Bad Request:伺服器無法理解請求的格式,客戶端不應該嘗試再次使用相同的內容進行請求
  • 401 Unauthorized:請求未經授權,這通常是因為未提供認證信息或認證失敗
  • 403 Forbidden:伺服器拒絕請求
  • 404 Not Found:伺服器找不到請求的網頁
  • 408 Request Timeout:請求超時,伺服器等候請求時發生超時

5xx 伺服器錯誤

  • 500 Internal Server Error:伺服器遇到了一個未知的錯誤,無法完成客戶端的請求
  • 501 Not Implemented:伺服器不支持請求的功能,無法完成請求
  • 503 Service Unavailable:伺服器目前無法使用(由於超載或停機維護)。通常,這只是暫時狀態

可以參考維基百科,或是 MDN

AJAX 實戰

接著我們可以利用網路上提供的免費 api 來練習。JSONplaceholder 就是其中一個免費的 api,他提供各種假資料讓我們免費串接和練習。我們今天就用它其中的一個 api 練習 👇,這是我們要用的 api 位置:https://jsonplaceholder.typicode.com/posts/1

💡還記得開頭提到的,對於前端串接資料來說,API 通常會是一個網址。
HTML
<h1 class="title"></h1>
<p class="content"></p>
JavScript
const title = document.querySelector('.title');
const content = document.querySelector('.content');

// 建立 XMLHttpRequest 物件
const xhr = new XMLHttpRequest();

// 監聽是否有回傳資料
xhr.addEventListener('readystatechange', () => {
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 請求完成且成功
    const response = xhr.responseText;

    // 將回傳的資料轉換成可以使用的 JS 物件
    const json = JSON.parse(response);
    // 將獲得的 title 和 body 給頁面
    title.innerText = json.title;
    content.innerText = json.body;
  }
});

// 用 open() 設置發送請求的方法
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);
// 用 send() 發送請求
xhr.send();

成果 👇

AJAX-response

使用 Fetch 串接 API

從上面就可以發現 XMLHttpRequest 的寫法非常複雜,而且若是有錯誤發生要處理,也非常麻煩,我們可能要寫很多 if-else 來判斷是哪裡錯誤,所以不管是 JQuery 還是 ES5 之後新增的 fetch 都是重新封裝 XMLHttpRequest 來讓其寫法更簡潔,接著來介紹更好用的 fetch 吧!

如果是新手的話,建議大概了解 XMLHttpRequest 就好,開發已經很少使用 XMLHttpRequest 了,更常使用 Fetch 或其他函式庫。

Fetch 的基本使用

Fetch 的語法非常簡單。

fetch(url, [options])
  .then((res) => console.log(res))
  • url: 後端提供的接口位置
  • options: 可選,串 api 時的一些設定,如果沒有設定 options,fetch 就會自動以 get 的方式取得資料。

Fetch 實戰

我們一樣來用 JSONplaceholder 提供的網址來實戰練習看看~

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then((response) => console.log(response));

Fetch 會回傳一個 Promise,所以我們可以用 .then() 來取得資料,而 response 通常代表是後端回傳的結果。而這是他回傳的結果👇

fetch-response

這是它回傳回來的資料,我們先不用全部看懂,只要先知道真正的資料在 body 裡面,不過 body 為甚麼寫 ReadableStream 呢?

是因為 Fetch 為了更好的效能,它不會一次讀取全部的數據才回傳,而是逐塊讀取數據,然後存在 ReadableStream 裡面,所以我們需要用某些方法將資料解析出來。

最常使用的方式是 response.json(),它會將資料自動解析成 json 格式,json 就像 js 的物件,所以解析成 json 後,我們就可以像操作 JavaScript 物件一樣獲取數據。

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then((response) => response.json())
  .then((json) => console.log(json));

  /*
    {
      "body" : "quia et suscipit...",
      "id" : 1,
      "title" : "sunt aut ...",
      "userId" : 1
    }
  */

可以看到他回傳的是一篇假文章,此時我們就可以像這樣去獲取文章的內容和標題。

const title = document.querySelector('.title');
const body = document.querySelector('.body')

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then((response) => response.json())
  .then((json) => {
    title.innerText = json.title;
    body.innerText = json.body;
  });

你就可以看到和用 AJAX 一樣的結果了!

在 Fetch 中帶入參數

有時候我們會要傳入一些參數來獲取特定的資料,例如我們想取得 id = 2 的文章,可以用 new URLSearchParams() 搭配 template string 使用,例如:


function getData(id) {
  fetch(
    `https://jsonplaceholder.typicode.com/posts?${new URLSearchParams({
      id: id
    })}`
  )
    .then((response) => response.json())
    .then((json) => console.log(json));
}

getData(2);

new URLSearchParams() 可以將物件轉換成 url 的查詢參數(param),舉例來說:

const params = { name: 'Jack', age: 25 };

const searchParams = new URLSearchParams(params);
console.log(searchParams.toString());
// name=Jack&age=25

Fetch 的常用選項

除了像上面那樣用 get 來取得資料,fetch 還提供第二個參數可以調整一些參數,例如將 method 改為 post

post 可以將前端的資料回傳給伺服器,我們一樣可以用 JSONplaceholder 來練習 post。

fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  body: JSON.stringify({
    title: 'fetch 教學',
    body: '這是有關 fetch 的一篇教學',
    author: 'this.web',
    userId: 1,
  }),
  headers: {
    'Content-type': 'application/json',
  },
})
  .then((response) => response.json())
  .then((json) => console.log(json)); // 檢查資料是否有回傳

/* 通常會回傳你傳的資料,以下
{
 title: 'fetch 教學'
 body: '這是有關 fetch 的一篇教學',
 author: 'this.web',
 userId: 1,
 ...
}
*/

讓我來一一解釋上面的選項:

  • method: api 請求的方法,例如 GET、POST、PUT、DELETE
  • body: 傳送的資料主體
  • headers: 請求頭,放一些有關於請求的相關訊息,像這裡的 'Content-type': 'application/json' 是指定伺服器回傳的資料為 json 格式

常見的 API 請求的方法:

  1. GET
    • 用於從伺服器獲取資源的詳細資料
    • 請求參數 (param) 通常包含在 URL 中
  2. POST
    • 用於在伺服器上建立新資源
    • 請求參數 (param) 包含在請求體 (request) 中
  3. PUT
    • 用於更新伺服器上的現有資源
  4. PATCH
    • 用於部分更新現有資源
    • 請求體 (request) 只包含需要更新的欄位
  5. DELETE
    • 用於從伺服器刪除指定的資源

我們 post 資料給伺服器後,它會回傳一些資料讓我們判斷我們是否有 post 成功,所以最後可以用 .then(console.log(json)) 來檢查。

Fetch 傳接 API 的錯誤處理

有時候我們不會那麼順利,可能在串接 API 時發生一些預料外的錯誤,但發生錯誤時,fetch 不會自動發現,需要我們手動的去判斷,這也是 fetch 的小缺點。

通常可以用 response.ok 來判斷是否有成功,我們故意把網址打錯來試試看 (/posts 打錯成 /post)。

const post = fetch('https://jsonplaceholder.typicode.com/post/100')
  .then((response) => {
    if (!response.ok) {
      throw new Error(response.status)
    }
    return response.json();
  })
  .then((json) => console.log(json))
  .catch((error) => console.log(error))
  // Error: 404

可以發現 catch 回傳一個 404,相信 404 大家都不陌生,代表網址錯誤 (請求的資源不存在),它是很常見的 HTTP code,而每個 HTTP code 都有各自的意思,可以參看前面我放的 HTTP Status code。

更詳細的 Fetch 用法可以參考 MDN

小結

最後總結一下,可以把 API 想像成一個提供特定服務的窗口,這些窗口都會有各自的規範,只要遵循這些規範,就可以使用它們提供的東西。

並且介紹了 AJAX 和 Fetch,也有提到 Promise,其實 API、Promise、asnyc/await 這幾個東西經常是一起出現的,對於前端新手來說可能需要一點時間來理解,如果有任何問題都可以傳 email 或直接私訊我的 IG 來問我~!

那今天就這樣,希望能讓你了解何謂 API,並知道前端要怎麼 API,老樣子,我們下篇貼文見~!

相關系列文章