axios拦截器
axios特性
- 从浏览器创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF
axios拦截器
在请求或响应被 then 或 catch 处理前拦截它们。
js
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
具体实现
新建request.js,写入以下内容:
js
import axios from 'axios';
import qs from 'qs';
//操作正常code,支持String、Array、int多种类型
const successCode = [200, 1];
//登录失效code
const invalidCode = -1;
//无权限code
const noPermissionCode = 401;
// 请求超时时间(毫秒)
const timeout = 2000;
// 基础url地址
const baseURL = '/api'
/**
*
* @description 处理code异常
* @param {*} code
* @param {*} msg
*/
const handleCode = (code, msg) => {
switch (code) {
// 掉线
case invalidCode:
alert('您已掉线,或者访问权限出错,请重新登录!');
break;
// 无权限
case noPermissionCode:
router.push({ path: '/401' }).catch(() => { });
break;
// 其他情况
default:
alert(msg || `后端接口${code}异常`);
break;
}
};
// 创建axios实例
const instance = axios.create({
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL,
// 指定请求超时的毫秒数
timeout,
// 自定义请求头
headers: {
'Content-Type': 'application/json;charset=UTF-8',
}
});
// 请求前拦截
instance.interceptors.request.use(
(config) => {
// 如果请求头声明需要formData数据,则使用qs进行处理
if (
config.data &&
config.headers['Content-Type'] === 'application/x-www-form-urlencoded;charset=UTF-8'
)
config.data = qs.stringify(config.data);
// 也可以在这里对接口传递公共参数
return config;
},
(error) => {
// 抛出错误
return Promise.reject(error);
}
);
// 响应拦截
instance.interceptors.response.use(
(response) => {
const res = response.data;
const { data } = response;
const { code, msg } = data;
// 操作成功
// 此处根据请求返回修改,成功code
if (successCode.indexOf(code) !== -1) {
return res;
} else {
// 请求失败
// 校验失败code,处理场景
handleCode(code, msg);
return Promise.reject();
}
},
(error) => {
const { response, message } = error;
// 如果返回有data,校验失败code
if (error.response && error.response.data) {
const { status, data } = response;
handleCode(status, data.msg || message);
return Promise.reject(error);
} else {
// 提示其他异常
let { message } = error;
if (message === 'Network Error') {
message = '后端接口连接异常';
}
if (message.includes('timeout')) {
message = '后端接口请求超时';
}
if (message.includes('Request failed with status code')) {
const code = message.substr(message.length - 3);
message = '后端接口' + code + '异常';
}
ElMessage.error(message || `后端接口未知异常`);
return Promise.reject(error);
}
}
);
export default instance;
在需要使用的页面进行调用
js
import request from '@/utils/request.js';
request({
url: '/login', // /api/login
method: 'post',
data: {
account: 'admin',
password: '123456'
},
}).then(res => {
// 处理逻辑
console.log(res);
});
进一步分离封装
上一步咱们将axios拦截器进行了封装,一般项目工程化会将所有的接口封装到一个js中
下面是封装了几个跟用户信息相关的接口:
js
import request from '@/utils/request.js';
export const login = async (data) => {
return request({
url: '/login',
method: 'post',
data,
});
};
export const getUserInfo = (accessToken) => {
return request({
url: '/userInfo',
method: 'get',
data: {
tokenName: accessToken,
},
});
};
export const logout = () => {
return request({
url: '/logout',
method: 'post',
});
};
export const register = async () => {
return request({
url: '/register',
method: 'post',
});
};