Nuxt3 请求封装

1,244 阅读1分钟

fetch.ts

import { hash } from 'ohash'
import type { UseFetchOptions } from '#app'
import { Message } from '@arco-design/web-vue'
import { useUserStore } from '@/stores'

// 处理错误状态码
const handleError = (status: number): void => {
  const ErrorStatusMap = {
    400: '请求失败!请您稍后重试',
    401: '登录失效!请您重新登录',
    403: '当前账号无权限访问!',
    404: '你所访问的资源不存在!',
    405: '请求方式错误!请您稍后重试',
    408: '请求超时!请您稍后重试',
    500: '服务异常!',
    502: '网关错误!',
    503: '服务不可用!',
    504: '网关超时!'
  }
  Message.error(ErrorStatusMap[status as keyof typeof ErrorStatusMap] || '请求失败!')
}

/**
 * useFetch 请求封装
 * @param { String } url 请求地址
 * @param { Object } options 请求配置项
 * @param { Object } headers 自定义header头, 单独设置headers区分请求参数,也好设置类型
 */
export const useFetchApi = async <T>(url: string, options: UseFetchOptions<ResOptions<T | any>>) => {
  // 设置key
  const key = hash(JSON.stringify(options) + url)
  const userStore = useUserStore()

  try {
    const res = await useFetch(url, {
      onRequest({ options }) {
        if (userStore.token) {
          if (!options.headers) {
            options.headers = {}
          }
          options.headers['JEECMS-Auth-Token' as keyof HeadersInit] = userStore.token
        }
      },
      onResponseError({ request, response, options }) {
        process.client && handleError(response.status)
      },
      key,
      ...options
    })
    const { error, data } = res
    // console.log('data', toRaw(data.value))
    if (data.value?.code !== 200) {
      // console.log('error', data.value)
      Promise.reject(data.value?.data.originalMessage || data.value?.message || t('text.server.error'))
    }
    if (error.value) {
      throw createError({
        statusCode: error.value.status,
        message: error.value as unknown as string
      })
    }
    return res
  } catch (error) {
    return Promise.reject(error)
  }
}

apis.ts

import { useFetchApi } from '@/utils/fetch'
import { prefix } from '../config'
import type * as User from './type'

/** 获取用户列表 */
export const getUserList = (body: { page: number; size: number; name: string }) => {
  return useFetchApi<ListOptions<User.UserItem[]>>(`${prefix}/user/page`, {
    method: 'POST',
    body: body
  })
}

/** 获取用户详情情 */
export const getUserDetail = (params: { id: string }) => {
  return useFetchApi(`${prefix}/user/detail`, { params })
}

使用

方式1

<script lang="ts" setup>
import { getUserList } from '@/apis'

const form = reactive({
  name: '',
  page: 1,
  size: 10
})

const userList = ref([])
const total = ref(0)

const getList = async () => {
  const { data }  = await getUserList(form)
  userList.value = data.value.data.records
  total.value = data.value.data.total
}

getList()

// 搜索
const search = () => {
  form.page = 1
  getList()
}
</script>

方式2

<script lang="ts" setup>
import { getUserDetail } from '@/apis'

const route = useRoute()
const { data } = await getUserDetail({ id: route.query.id as string })
const userInfo = ref(data.value.data)
// const userInfo = computed(() => data.value.data)
</script>