跳到主要内容

nuxt请求封装

  • 统一项目请求方式
  • 方便维护每个请求
  • 保证服务端和客户端同一数据源
  • 避免重复请求,导致数据不一致,状态不同步

需要考虑点​

  • 水合渲染问题,保证数据一致
  • 统一请求头
  • BaseURL
  • token
  • 超时
  • 拦截器
  • 统一错误处理
  • 请求缓存

useRequest封装​

  • server: false 是 Nuxt useFetch** /** useAsyncData** 自带的参数**
    • 当设置false时,表示不走SSR请求,走客户端请求
    • 用来控制这个请求是否在SSR服务端阶段执行
  • isMutation
    • 用来判断是不是 POST / PUT / PATCH / DELETE
    • 比如GET请求,默认可以走SSR
    • 比如POST、DELETE请求,这种涉及到修改数据的,不走SSR
      • 因为这类修改数据的请求,是用户触发的,需要在客户端阶段来执行
typescript
// composables/useRequest.ts

import type { UseFetchOptions } from '#app'
import type { NitroFetchRequest } from 'nitropack'

export function useRequest<
T,
R extends NitroFetchRequest = NitroFetchRequest
>(
request: R,
options: UseFetchOptions<T, R> = {}
) {
const config = useRuntimeConfig()
const token = useCookie<string | null>('token')

const method = String(
options.method ?? 'GET'
).toUpperCase()

const isMutation = ![
'GET',
'HEAD'
].includes(method)

const customFetch = $fetch.create({
baseURL: config.public.apiBase,
timeout: 10_000,

onRequest({ options }) {
const headers = new Headers(options.headers)

if (token.value) {
headers.set(
'Authorization',
`Bearer ${token.value}`
)
}

headers.set('X-Client', 'web')

options.headers = headers
},

onResponse({ request, response }) {
if (import.meta.dev) {
console.debug(
'[Request]',
request,
response.status
)
}
},

onResponseError({ request, response }) {
console.error(
'[Request Error]',
{
request,
status: response.status,
data: response._data
}
)

if (response.status === 401) {
// 登录状态失效处理
}

if (response.status >= 500) {
// 日志 / Sentry / 告警
}
}
})

return useFetch<T, R>(request, {
/**
* GET / HEAD:
* 默认支持 SSR
*
* POST / PUT / PATCH / DELETE:
* 默认只在客户端执行
*/
server: !isMutation,

/**
* 查询请求默认立即执行
* mutation 默认等待 execute()
*/
immediate: !isMutation,

lazy: false,

dedupe: 'cancel',

/**
* 调用方配置优先级最高
*/
...options,

/**
* 保留 useFetch 的 SSR / Hydration 能力
*/
$fetch: customFetch
})
}

SSR请求示例​

typescript
const { data } = await useRequest('/articles')

客户端请求示例​

typescript
const { data } = await useRequest('/recommend', {
server: false
})