- 问题: 在 axios 封装时, 我们经常在响应拦截器中做统一的错误异常处理以减少重复代码, 但是有些情况又想要自行处理失败和异常, 怎么办?
- 解决: 可以通过给 axios 扩展 skipErrorHandler 请求入参的方式实现, 以下是具体实现
封装
以下代码重点突出错误处理逻辑, 已简化 axios 的其他封装逻辑
假设接口响应数据结构为:
{
errcode:0, // 错误码, 0-成功, 其他-失败
errmsg: "失败原因" // 失败信息
data: {...} // 响应数据
}
// src/utils/request.ts
import { message, notification } from 'antd';
import axios from 'axios';
import type { AxiosError, AxiosResponse } from 'axios';
// 扩展 axios 的 TS 类型
declare module 'axios' {
export interface AxiosRequestConfig {
/** 是否跳过统一错误处理 */
skipErrorHandler?: boolean;
}
}
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
405: '请求方法不被允许。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
const request = axios.create();
// 响应拦截器
request.interceptors.response.use(
(response: AxiosResponse) => {
const res = response.data;
const { skipErrorHandler } = response.config;
const { errcode, errmsg = '未知的业务处理错误' } = res;
// 选择性忽略错误码统一处理
if (errcode && !skipErrorHandler) {
message.error(errmsg);
}
return res;
},
(error: AxiosError) => {
const { skipErrorHandler } = error.config;
// 忽略统一异常处理
if (skipErrorHandler) {
return Promise.reject(error);
}
// 异常统一处理
const status = error.response?.status ?? '';
const message = codeMessage[status] || error.message || '未知异常';
const url = error.config.url ?? '';
notification.error({
message: `请求错误 ${status}: ${url}`,
description: message,
});
return Promise.reject(error);
},
);
export default request;
使用
// src/services/user.ts 定义请求方法
export async function updateName(data: {
name: string;
id: number;
}): Promise<API.BaseType<boolean>> {
return request.put('/user/update/password', data, {
skipErrorHandler: true, // 忽略拦截器中的错误处理
});
}
// src/pages/xxx.tsx 发起请求, 自行处理错误
const editName = async () => {
try {
const res = await updateName({ name: 'lisa', id: 1 });
if (res.errcode) {
// 修改成功
} else {
// 业务失败处理
}
} catch (error) {
// 接口异常处理
}
};
总结
通过给 axios 的入参扩展一个自定义参数(skipErrorHandler), 在响应拦截器中拿到这个参数, true表示忽略统一的错误处理逻辑, false反之