iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0
佛心分享-SideProject30

NUXT3xVUE3xPINIA: 從零開始寫電商系列 第 10

[Day 10] 設定CORS及製作API Handling feat. Composable

  • 分享至 

  • xImage
  •  

打地基階段,本篇要將call API的系統設計好,這是經過幾次個人專案後,覺得用起來最適合的方式。產品相關的功能是直接拿dummyjson的API,所以這邊一併把CORS也設定一下。

目錄

  • Call API的設計
  • oFetch
  • Composable: useAPI說明
  • 完成useAPI
  • 測試useAPI
  • 閒聊碎碎念

Call API的設計

說明一下我的資料系統設計,call API時的系統流程會長這樣:
store call useAPI -> useAPI send request

  • store: 中央資料、狀態中心。
  • useApi: Composable,統一處理sending request、API狀態管理及error handling的動作。

oFetch

oFetch來call API,官網有指出oFetch是全域的功能了,所以就不安裝其他工具了(aixos):

Nuxt uses ofetch to expose globally the $fetch helper for making HTTP requests.

Composable: useAPI說明

整個專案都會透過useApi去拿後端資料,
useApi這隻composable裡有兩個響應式資料:

  • data: any -> 回傳資料
  • isLoading: boolen -> 是否正在傳遞資料

完成useAPI

這是最後的樣子:

import { FetchError } from "ofetch";
export default function useAPI() {
  const fetchData: Ref<any> = ref();
  const isLoading: Ref<boolean> = ref(false);

  const callAPI = async (url: string) => {
    isLoading.value = true;
    
    try {
      const response = await $fetch(url, { responseType: 'json' });
      fetchData.value = response;

    } catch (error) {
      const FetchError = error as FetchError;
      if (FetchError.response && FetchError.response.status === 404) {
        throw showError({ statusCode: 404, statusMessage: 'API Not Found' })
      } else {
        throw showError({ statusCode: FetchError.response?.status, statusMessage: FetchError.message })
      }
      
    } finally {
      isLoading.value = false;
    }
  }

  return { 
    fetchData,
    isLoading,
    callAPI
  };
}

測試useAPI

  1. useStore.ts就定位
// ./stores/useStore.ts
import { defineStore } from 'pinia';
import useAPI from '~/composables/useApi';

const storeName = 'test';
export const useTest = defineStore(storeName, () => {
    const { 
        callAPI, 
        fetchData,
        isLoading
    } = useAPI();

    const testCallApi = async () =>  {
        return callAPI(`https://dummyjson.com/products`);
    }
    return {
        testCallApi,
        isLoading,
        fetchData
    }
});
  1. pages/index.vue使用store:
<script setup lang="ts">
// stores
const testStore = useTest();
const {
  testCallApi
} = testStore;
const {
  fetchData
} = storeToRefs(testStore);
onMounted(async () => {
  await testCallApi();
})
</script>

<template>
  <div>
    Page: index
    {{ fetchData }}
  </div>
</template>

<style scoped>
</style>
  1. 頁面長這樣
    day10

設定CORS

其實dummyjson的CORS是access-control-allow-origin: *不過還是寫一下吧~一樣,拿./stores/useStore.ts來做測試:

import { defineStore } from 'pinia';
import useAPI from '~/composables/useApi';

const storeName = 'test';
export const useTest = defineStore(storeName, () => {
    ...
    const testCallApi = async () =>  {
        return callAPI(`/api/products`);
    }
    return {
        testCallApi,
        ...
    }
});

接著在./pages/index.vue呼叫:

<script setup lang="ts">
// stores
const testStore = useTest();
const {
  testCallApi
} = testStore;
const {
  fetchData
} = storeToRefs(testStore);
onMounted(async () => {
  await testCallApi();
})
</script>

<template>
  <div>
    Page: index
    {{ fetchData }}
  </div>
</template>

<style scoped>
</style>

最後網頁成功顯示:
成功顯示

閒聊碎碎念

一開始在K call API的功能時,我是直接寫在一般assets/js/xx.js的檔案裡,因為也覺得沒毛病;後來一個資深前輩跟我說,像我這樣的規劃,寫在composable裡會更好,所以就改成這樣的做法,覺得非常的合理。


上一篇
[Day 9] 來了!建立專案+設定基本架構
下一篇
[Day 11] Error handling
系列文
NUXT3xVUE3xPINIA: 從零開始寫電商17
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言