Skip to content

Vue 3 實戰:打造高效能、可重複使用的 useFetch 非同步封裝

在現代前端開發中,處理 API 請求不只是「拿到數據」而已,更包含了 Loading 載入中Error 錯誤處理 以及 數據響應性。今天我們示範如何結合 Axios 與 Composable,打造一個靈活且具備完整錯誤傳遞機制的 useFetch

核心設計:封裝 Axios 與錯誤向上傳遞

在進行二次封裝時,最容易犯的錯誤就是「吃掉錯誤」。為了讓呼叫端(如元件)能根據錯誤進行後續處理(例如顯示通知),我們必須在 Axios 封裝層使用 throw err

修改 utils/axios/api.js

確保當 API 發生異常時,錯誤能被正確拋出到 Composable 層。

js
// utils/axios/api.js
import instance from "./instance";

export default {
  async GET(endPoint, config = {}) {
    try {
      const res = await instance.get(endPoint, config);
      return res.data;
    } catch (err) {
      console.log("Axios 封裝方法失敗:", err);
      throw err; // 重新拋出錯誤給上層處理
      // return Promise.reject(err); // 也可以這樣寫
    }
  },
};

實作 useFetch Composable

這個 Composable 的目標是:只要傳入 endPoint,就自動回傳數據、載入狀態與錯誤訊息。

js
// composables/useFetch.js
import api from "@/utils/axios/api";
import { ref } from "vue";

export default (endPoint, config = {}) => {
  const data = ref(null);
  const isLoading = ref(false);
  const error = ref(null);

  async function loadData() {
    isLoading.value = true;
    error.value = null;

    try {
      const res = await api.GET(endPoint, config);

      if (res) data.value = res;
    } catch (err) {
      error.value = err;
    } finally {
      isLoading.value = false;
    }
  }

  loadData();

  return { data, error, isLoading };
};

在元件中實戰應用:多 API 呼叫的命名藝術

當一個頁面需要同時呼叫多個 API(例如:使用者清單、產品清單)時,使用 ES6 解構賦值(Destructuring)並重新命名 是維持程式碼清晰度的最佳實踐。

vue
// App.vue
<script setup>
import useFetch from "@/composables/useFetch";

const {
  data: users,
  isLoading: usersIsLoading,
  error: usersError,
} = useFetch("/users");
</script>

<template>
  <div v-if="!usersIsLoading">
    <h2>Users</h2>
    <p v-if="usersError" v-text="usersError"></p>
    <ul v-else-if="users?.length">
      <li v-for="u in users" :key="u.id">
        <pre v-text="u"></pre>
      </li>
    </ul>
    <p v-else>No users data.</p>
  </div>
  <div v-else>Loading...</div>
</template>

關鍵技術點解析

為什麼要用「解構重命名」?

useFetch 中,回傳的屬性名稱通常是固定的 dataisLoadingerror。但在大型專案中,您會在同一個元件呼叫多個 Composable。透過 data: users 這種寫法,不僅解決了命名衝突,也增加了程式碼的 語意化

錯誤處理的正確姿勢

許多開發者會在 Composable 裡直接 console.log 錯誤後就結束了。但正確的做法是更新 error 響應式變數,讓 UI 能夠根據錯誤狀態顯示對應的視窗或文字說明,這對使用者體驗(UX)至關重要。