axios特性
- 从浏览器创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF
axios拦截器
在请求或响应被 then 或 catch 处理前拦截它们。
// 添加请求拦截器 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,写入以下内容:
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;
在需要使用的页面进行调用
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中
下面是封装了几个跟用户信息相关的接口:
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', }); };