复杂前端系统的接口策略统一方案

238 阅读1分钟

一、前言:接口混乱,是大型前端系统的最大隐患

广告平台项目中,前期接口调用写法五花八门:

  • 直接在组件里 axios.post
  • 缺乏统一 loading、报错提示、缓存策略
  • 同一个接口被不同模块重复封装
  • 多模块间接口定义重复、不兼容

这些问题严重影响维护性、协作效率和系统稳定性。

我主导构建了一整套“接口分层 + 类型安全 + 自动化生成”的调用策略。


二、接口策略总体架构

+---------------------+
|   页面/模块调用层    |
+---------------------++---------------------+
|   业务接口封装层    |   ➜  自动生成 API 类型 + hooks
+---------------------++---------------------+
|   通用请求适配器    |   ➜  包含 baseURL、token、loading、报错处理
+---------------------+

三、通用请求适配器封装

// request.ts
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE,
  timeout: 10000
})

request.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer ${getToken()}`
  return config
})

request.interceptors.response.use(
  res => res.data,
  err => {
    showError(err.response?.data?.message || '请求异常')
    return Promise.reject(err)
  }
)

四、接口封装层(按模块划分)

以广告模块为例:

// api/ad.ts
export const getAdList = (params) => request.get('/ad/list', { params })
export const createAd = (data) => request.post('/ad/create', data)

每个模块的接口独立,导出统一管理:

export * as adApi from './api/ad'

五、自动生成接口类型(OpenAPI → TypeScript)

通过 openapi-typescript + swagger.json 实现:

npx openapi-typescript http://localhost:3000/swagger.json -o types/api.d.ts

生成结果:

export namespace paths {
  '/ad/list': {
    get: operations['GetAdList']
  }
}

自动绑定到封装函数:

import type { paths } from '@/types/api'

export const getAdList = (params: paths['/ad/list']['get']['parameters']['query']) => {
  return request.get('/ad/list', { params })
}

六、接口调用的 useXXX Hook 生成策略

封装模块级调用 hook:

export const useAdList = () => {
  const data = ref([])
  const loading = ref(false)

  const fetch = async (params) => {
    loading.value = true
    try {
      data.value = await getAdList(params)
    } finally {
      loading.value = false
    }
  }

  return { data, loading, fetch }
}

七、缓存策略支持

对高频/慢接口使用本地缓存 + 过期机制:

const useCachedRequest = (key, fn, ttl = 300000) => {
  const cacheKey = `${key}:${JSON.stringify(args)}`
  const now = Date.now()
  const cached = localStorage.getItem(cacheKey)
  if (cached && now - cached.timestamp < ttl) return cached.data
  const data = await fn()
  localStorage.setItem(cacheKey, { timestamp: now, data })
  return data
}

八、错误处理统一化

抽象 error hook:

export const useErrorHandler = () => {
  const handle = (err) => {
    if (err.status === 403) showMessage('无权限')
    else showMessage(err.message || '系统异常')
  }
  return { handle }
}

九、结果成效

  • 所有接口调用统一结构,减少重复封装 70%
  • 所有接口类型自动生成,类型准确率达 95%
  • Loading、Error、Token 逻辑不再重复写

十、总结

接口不是“能调通就行”,而是整个前端系统的数据基础。

通过策略统一、模块解耦、自动类型、hook 化调用,我们构建了一套稳定、高效、类型安全、可维护的接口体系。

这也是我在大型系统中非常核心的一项工程能力。