在项目中使用了umi-request 来处理请求拦截,但是使用时发现了一个问题:
在请求接口时,如果成功则返回内容,否则会直接报错,无法获取到服务器返回的具体报错信息,
例如后台返回的状态码400,在umi request errorhandler里捕捉不到。类似这样的400错误,提示信息在errhandle里统一处理
目前只能用状态码粗略匹配
而服务器返回的信息有三种情况:
能够在umi-request统一处理错误信息之前获取到服务器返回的内容并处理
https://github.com/ant-design/ant-design-pro/issues/4794
在errorHandler中直接获取data,然后进行处理或直接返回即可
import { extend } from 'umi-request';
import { message } from 'antd';
import config from '../config/dev';
import { history } from 'umi';
import { isFormData } from '@/utils';
const API_URL = config.apiBase;
const codeMessage = {
200: '服务器成功返回请求的数据',
201: '新建或修改数据成功',
202: '一个请求已经进入后台排队(异步任务)',
204: '删除数据成功',
400: '请求有误',
401: '用户名或密码错误',
403: '用户得到授权,但是访问是被禁止的',
404: '请求失败,结果不存在',
405: '操作失败',
406: '请求的格式不可得',
410: '请求的资源被永久删除',
422: '操作失败',
500: '服务器发生错误,请检查服务器',
502: '网关错误',
503: '服务不可用,服务器暂时过载或维护',
504: '网关超时',
};
type mapCode =
| 200
| 201
| 202
| 204
| 400
| 401
| 403
| 404
| 405
| 406
| 410
| 422
| 500
| 502
| 503
| 504;
/**
* 异常处理程序
*/
const errorHandler = (error: { response: Response; data: any }): Response => {
const { response, data } = error;
if (
response &&
response.status === 401 &&
history.location.pathname === '/login'
) {
return response;
}
if (data?.error) {
message.error(data.error.message);
return response;
}
if (response && response.status) {
const errorText =
codeMessage[response.status as mapCode] || response.statusText;
message.error(`${errorText}`);
} else if (!response) {
message.error('无法连接服务器');
}
return response;
};
/**
* 配置request 请求时的默认参数
*/
// console.log(process.env.UMI_ENV,process.env.API_ROOT);
const request = extend({
timeout: 20000,
prefix: process.env.NODE_ENV === 'development' ? API_URL : '/api/',
errorHandler, // 默认错误处理
// credentials: 'include', // 默认请求是否带上cookie
});
// token 拦截器
request.interceptors.request.use((url: string, options: any) => {
let newOptions: any = { ...options };
const token = localStorage.getItem('token');
if (token) {
newOptions.headers['Authorization'] = token ? `Bearer ${token}` : null;
}
newOptions.headers['Content-Type'] = 'application/json';
if (isFormData(newOptions.body)) {
delete newOptions.headers['Content-Type'];
}
return {
url,
options: newOptions,
};
});
request.interceptors.response.use((response, options: any) => {
try {
const token = localStorage.getItem('token');
if (
response.status === 401 &&
history.location.pathname === '/login' &&
options.method === 'POST'
) {
message.error('用户名或密码错误');
console.log(response, options);
return;
}
if (
response.status === 401 ||
response.status === 403 ||
(!token && history.location.pathname !== '/login')
) {
// message.error('登录已过期,请重新登录');
localStorage.removeItem('token');
localStorage.removeItem('auth');
history.push('/login');
return;
}
// if (!response.ok) {
// return Promise.reject(response)
// }
} catch (error) {
return Promise.reject(error);
}
// console.log(response, 'response')
return response;
});
export default request;