axios 分层封装:多后端鉴权与 401 处理
前端工程36 阅读约 5 分钟
我的博客后台要和两个后端打交道:主站 API(NestJS)和一个独立的 AI 对话服务(Cloudflare Worker)。它们的地址不同、鉴权头不同、响应信封也不同。如果到处 axios.get(...) 再手动加 header、手动解包,重复代码和遗漏迟早出事。
正解是分层封装:每个后端一个专属 axios 实例,公共逻辑塞进拦截器。
每个后端一个实例
不同后端 = 不同 baseURL + 不同拦截器配置。各建一个实例,互不干扰:
// ai-http.ts —— 专给 AI 服务用的实例
const instance = axios.create({ baseURL: CONFIG.aiApiBase })
// 请求拦截器:自动带上管理端令牌
instance.interceptors.request.use((config) => {
const token = getAccessToken()
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})
主站 API 那个实例同理,但 baseURL 指向 CONFIG.apiBaseUrl,鉴权方式按它的约定来。两个实例各自封装各自的差异,调用方完全无感。
响应拦截器:解包 + 统一报错 + 401 处理
AI 服务返回的是一个统一信封 { status, message, result }。响应拦截器负责「拆信封、抛业务错、处理鉴权失效」:
instance.interceptors.response.use(
(response) => {
const body = response.data as AiResponse
if (body.status !== 'success') {
message.error(body.message || '请求失败')
return Promise.reject(body)
}
return body // 统一返回信封,调用方拿 .result
},
(error) => {
if (error.response?.status === 401) {
// 令牌失效:清登录态 + 跳登录页,避免停在一个「点啥都 401」的坏页面
clearAuth()
redirectToLogin()
}
message.error(error.response?.data?.message || '网络异常')
return Promise.reject(error)
},
)
把它包成带类型的小 API,业务里调用极简:
export default {
get: <T = any>(url: string, params?: object) =>
instance.request({ method: 'get', url, params }) as Promise<AiResponse<T>>,
delete: <T = any>(url: string) =>
instance.request({ method: 'delete', url }) as Promise<AiResponse<T>>,
}
业务层:const { result } = await aiHttp.get<ChatSession[]>('/admin/chat-sessions')——鉴权、解包、报错、401 跳转,一个都不用操心。
为什么不共用一个实例
有人会想「一个实例 + 动态 baseURL 不就行了」。不行,因为两个后端的横切逻辑不一样:
- 鉴权头可能不同(一个
Authorization: Bearer,另一个也许是别的方案); - 响应信封结构、错误判定字段不同;
- 401 的处理时机和跳转目标可能不同。
把它们塞进一个实例,拦截器里就会出现一堆 if (isAiBackend) 的分支,越长越乱。一个后端一个实例让每份拦截器都专注、简单、好测。
401 的「兜底登出」很重要
最容易被忽略、体验影响最大的是 401 处理。令牌过期后如果不集中处理,用户会停在一个「点哪都失败、又没提示」的死页面。在响应拦截器里统一捕获 401 → 清登录态 → 跳登录页,把这个糟糕体验一次性堵死。这也呼应了一个排障教训:曾经因为某个跨服务调用返回了非 2xx,触发了误判登出——把「什么情况算鉴权失效」收敛到一处,才好统一推敲、避免误伤。
小结
面对多后端,别用一个万能 axios 硬扛。一个后端一个实例,请求拦截器管鉴权、响应拦截器管解包与报错、401 统一兜底登出。差异封在实例内部,业务层只看到一个类型友好的简单 API。
相关文章
评论 (6)
moonlight
SSR 下只在客户端才有的 window 一般怎么处理?
蝈蝈
+1,正想问这个
这博客质量是真的高
南风
博主更新好勤快,学到了
Echo
正好踩到这个坑,及时雨啊
tobeornot
自定义 Hook 抽离逻辑确实清爽很多





