# 前端如何管理 API (下)- 一些經驗談

# 1. API endpoint 設定

在開發的時候,總不可能都打 production 的 API(如果是的話可能要注意了...),而是會根據環境不同而設定不同的 API domain,例如在 dev 的時候就用 api.app-dev.com 在 staging 時用 api.app-staging.com 等等,這時候就很適合用下列的方式來管理你的 API:

const API_BASE_URLS = {
  development: 'api.app-dev.com',
  staging: 'api.app-staging.com',
  production: 'api.app.com',
};

const getAPIBase = (env = process.env.NODE_ENV) => API_BASE_URLS[env] || API_BASE_URLS.development;

你可以搭配 webpack 的 DefinePlugin 在打包的時候自動根據環境變數來設定 API。

# 2. 利用 axios 等套件統一管理 API

如果你每次在呼叫 API 的時候都直接用 fetch 或是 ajax 呼叫,當後端改變實作,例如原本 api 在同一個 domain,但因為後端想要搬到別的 domain 時,為了讓 cookie 順利運作,就需要額外加上 credenticals 的設定。

這時候如果你沒有額外包裝的話,就要到處去看每個用到 fetch API 的地方然後一個個修改,API 一多改起來就會很麻煩(雖然也可以直接尋找替代,但百密總有一疏)。這時候如果有統一包裝起來的話就比較方便,像 axios (opens new window) 可以用 axios.create() 來建立一個 client,管理上就會舒服許多。

當然你也可以自己提供選項來做包裝,不一定要用 axios,不過 axios 真的挺好用的,尤其是 interceptor 的功能,簡直是後端改 API 規格時的救星,值得參考一下。

# 3. 至少在最外層統一處理錯誤

這也是蠻建議將 API 包成比較通用的函數的原因之一,你可以在裡面做一次最基本的錯誤處理,例如跳個錯誤彈窗之類的。

fetch 或是 ajax 寫久了難免就直接偷懶不寫 catch 或 onerror 了,如果每個 API 都有自己再寫一次相同的錯誤處理邏輯又顯得有些麻煩。

const makeAPIClient = ({
  baseURL,
  retry,
  timeout,
  onRequestError,
  headers,
  credentials,
}) => ({
  endpoint,
  method,
  body,
}) => {
  return fetch(baseURL ? `${baseURL}/${endpoint}` : endpoint, {
    headers,
    credentials,
    method,
    body,
  })
  .then() // do your retry logic 
	.catch(onRequestError)
}

實作起來大概像這樣,還有很多細節可以考慮。

# 4. error logging

如果有使用一些 error reporting 的平台(像是 sentry、rollbar 或是自家平台等),可以將錯誤記錄到後台方便追蹤,如果不知道選哪個蠻推薦 sentry (opens new window) 的,介面好看而且很好追蹤錯誤,數據一目瞭然。

# 5. 實作列表類 API 時要注意的事

最重要的就是注意後端的 SQL 有沒有寫好,像是:

  • 是否有提供分頁參數,還是一次就噴幾萬筆給前端
  • 依照使用需求,是否有設計 sortBy, order 等功能?
  • 是否需要做無限滾動?
  • 是否有設計 limit 參數,limit 參數如果是小數、負數、大數是否有做處理?

分頁參數這點很重要,有時候後端會嫌麻煩又覺得資料量不大就索性不做了,一旦資料量增長,回應速度跟渲染多筆資料時就會有效能上的影響。

再來是 sortBy 與 order 的功能,你或許會覺得這在前端也可以做到,但要記住前端只能對**「已經存在瀏覽器的資料做排序」**,也就是除非拿到全部的資料,不然在前端正確實作 sortBy 與 order 是不可能的事。

如果需要實作無限滾動,要考量的問題就更多了,當資料量太大時,你可能需要實作 windowing 來增加效能,或是直接限制每次 render 的資料量,這點我們在進階篇會談到。

# 小結

這三天我們一起探討了前端在實作 API 時可能需要考量的事,當然根據使用場景不同,或許不用做到那麼完美,可能也有許多沒有提到的事。但我盡量總結了在串接 API 時可能會遇到的事,希望大家可以少走一些冤枉路。