一、前言:接口混乱,是大型前端系统的最大隐患
广告平台项目中,前期接口调用写法五花八门:
- 直接在组件里
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 化调用,我们构建了一套稳定、高效、类型安全、可维护的接口体系。
这也是我在大型系统中非常核心的一项工程能力。