Axios 封裝實戰:打造高效能且易維護的 API 請求層
在開發中大型專案時,如果每次發送 API 請求都要重複設定 timeout、headers 或手動處理 401 錯誤,不僅程式碼冗餘,管理起來更是噩夢。為了提高 程式碼維護性 與 擴充性,對 Axios 進行二次封裝是前端開發者的必修課。
為什麼需要封裝 Axios?
傳統的寫法會將邏輯與配置混在一起,如下所示:
js
axios({
method: "get",
url: "https://jsonplaceholder.typicode.com/users",
timeout: 5000,
headers: {
"Content-Type": "application/json",
Authorization: "xxx",
},
})
.then((res) => {
console.log(res.data);
})
.catch((err) => {
const status = err?.response?.status;
if (status === 401) console.log("權限過期");
if (status === 403) console.log("無此權限");
console.log(err);
});小提醒
透過封裝,我們可以將 統一配置、錯誤處理 與 環境變數 抽離,實現更優雅的程式碼結構。
如何為 Axios 進行封裝
我們必須統一設定,如:請求標頭、狀態碼、超過請求的時間、不同環境設置不同接口,並將請求的方法再次封裝與設置請求與回應的攔截器。
Axios 實體化 (Create Instance)
利用 axios.create 建立實體,可以針對不同的 API 來源(如:測試環境 vs 正式環境)設置不同的基礎路徑。
baseURL:建議搭配環境變數,例如:process.env.VITE_API_URL來切換環境。timeout:統一設置請求超時時間,避免無限等待。headers:設置預設的請求標頭。如果有特殊標頭以參數的方式傳入,將會覆蓋預設的請求標頭。
js
const instance = axios.create({
baseURL:
import.meta.env.VITE_API_URL || "https://jsonplaceholder.typicode.com",
timeout: 5000,
headers: {
"Content-Type": "application/json",
},
});Axios 方法封裝 (API Methods)
將常用的 GET、POST 等方法再次封裝,自訂回傳格式,例如:直接回傳 res.data,能讓呼叫端的程式碼更乾淨。
js
const api = {
async GET(endPoint, config = {}) {
try {
const res = await instance.get(endPoint, config);
return res.data;
} catch (err) {
return Promise.reject(err);
}
},
async POST(endPoint, data, config = {}) {
try {
const res = await instance.post(endPoint, data, config);
return res.data;
} catch (err) {
return Promise.reject(err);
}
},
};Axios 攔截器 (Interceptors) 的核心應用
攔截器是封裝的靈魂,它能在「請求送出前」與「回應收到後」進行加工。
請求攔截 (Request Interceptor)
主要用於 自動注入 Token。不需要在每次發送 API 時手動傳入 Authorization。
回應攔截 (Response Interceptor)
主要用於 統一錯誤處理,例如:401 自動登出、500 系統錯誤提示。
js
function interceptors() {
instance.interceptors.request.use(
(req) => req,
(err) => {}
);
instance.interceptors.response.use(
(res) => res,
(err) => {}
);
}
interceptors();再做一點補強,如下:
js
function interceptors() {
instance.interceptors.request.use(
(req) => {
const token = localStorage.getItem("token");
if (token) req.headers.Authorization = `Bearer ${token}`;
return req;
},
(err) => Promise.reject(err)
);
instance.interceptors.response.use(
(res) => res,
(err) => {
switch (err?.response?.status) {
case 401:
console.log("權限過期");
break;
case 403:
console.log("沒有權限");
break;
case 500:
console.log("伺服器錯誤");
break;
default:
console.log("網路有問題");
break;
}
return Promise.reject(err);
}
);
}
interceptors();參考來源:Axios
Axios 封裝的分層職責
透過這樣的結構,當 API URL 變更或需要新增全域錯誤提示時,您只需要修改一個地方,就能影響整個專案,這就是封裝的核心價值!
| 模組檔案 | 主要職責 |
|---|---|
| instance.js | 負責 axios.create 基礎設定與環境變數對應。 |
| api.js | 封裝成更易讀的 GET / POST 方法,簡化回傳資料格式。 |
| interceptors.js | 集中處理請求前的 Token 注入與回應後的狀態碼判斷。 |
