vue - vue项目对axios请求的封装
axios介绍
axios是基于promise的网络请求库,可以在nodejs和浏览器中运行。在服务端axios使用原生的nodejs的http模块,在客户端浏览器中则而是用xmlhttprequests,本质是对XHR的封装,只不过是promise的实现版本;
功能:
- 从浏览器中创建 XMLHttpRequest
- 从 node.js 中创建 http 请求
- 支持 Promise API
- 拦截请求和响应和转换数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防止 XSRF 攻击
开始封装:
1,新建myAxios.js和backend.js;
myAxios主要是对axios的封装,而backend是对后端状态码的判断;
myAxios.js:
import Axios from 'axios';
import { ErrorToken, GlobalResponseCode, BusinessResponseCode, ApiResult } from '@/api/backend';
import router from '@/router';// 全局配置
const axios = Axios.create({timeout: 60 * 1000, // 超时时间 1分钟headers: { 'Content-Type': 'application/json;charset=UTF-8' }, // axios默认的请求类型 json类型进行传输
});/* 请求拦截处理token的情况 请求头里面可以随意添加属性 */
axios.interceptors.request.use((config) => {const token = localStorage.getItem('token');if (token) {config.headers.authToken = token;}return config;
});// 响应拦截
axios.interceptors.response.use((response) => {// 我们一般在这里处理,请求成功后的错误状态码 例如状态码是500,404,403return Promise.resolve(response);},(error) => {// 服务器响应发生错误时的处理Promise.reject(error);}
);/* 定义类 */
/* 注意 get多次相同的请求会出现304 post就不会 */
class MyAxios {// 1,get请求get(url, params) {console.log('params', params);return this.request(axios.get(url, params));}// 2,post请求post(url, data) {return this.request(axios.post(url, data));}// 3,put请求put(url) {return this.request(axios.put(url));}/统一响应封装 */async request(axiosRequest) {try {const res = await axiosRequest;// axios请求会返回一个promise所以此处使用await进行接收 如果有异常使用 try catch进行捕获// 请求失败的情况if (!res.data || res.data.code != '000000') {this.resCodePrompt(res.data.code);console.warn('SeverError', res);// 处理失败结果return new ApiResult().setError(res.data);}// 请求成功的处理return new ApiResult().setSuccess(res.data);} catch (error) {// TODO 这里需要验证失败的情况const res = error.response;// 根据状态吗进行提示this.resErrorPrompt(res);return new ApiResult().setNetworkError();}}/效验返回码 */resCodePrompt(resCode) {// 判断是否是token的问题if (ErrorToken.includes(resCode)) {this.$message({ type: 'error', message: '登录凭证无效,请重新登录' });router.push('/login');}// 判断不是token的问题const message = GlobalResponseCode[resCode] || BusinessResponseCode[resCode];if (message) {return this.$message({ type: 'error', message: '登录凭证无效,请重新登录' });}}/错误的返回码处理 */resErrorPrompt(res) {if (!res) {this.$message({ type: 'error', message: '网络错误!' });} else if (res.status === 404) {this.$message({ type: 'error', message: '找不到资源!' });} else if (res.status === 500) {this.$message({ type: 'error', message: '内部错误!' });} else {// 其余统一提示状态码this.$message({ type: 'error', message: `${res.status}` });}}
}export const myAxios = new MyAxios();
backend.js
/结果封装 */
export class ApiResult {/请求是否成功 */isSuccess = false;/请求结果状态 */stu = RequestStu.success;/状态码 */code = '000000';/描述信息 */msg = '';/请求结果数据 */data = null;/后端返回成功 */setSuccess(res) {this.isSuccess = true;this.stu = RequestStu.success;this.msg = res.msg;this.data = res.data;this.code = res.code;console.log('this:', this);return this;}/ 后端返回失败 */setError(res) {this.stu = RequestStu.error;this.msg = res.msg;this.code = res.code;return this;}/ 网络错误 */setNetworkError() {this.stu = RequestStu.networkError;return this;}
}/错误响应吗 关于token验证的 */
export const ErrorToken = ['000002', '000003', '000004'];/全局响应码 000000--000100(包括000000和000100)*/
export const GlobalResponseCode = {/成功*/'000000': '成功',/请求失败 */'000001': '请求失败',/令牌为空 */'000002': '请重新登录',/令牌过期 */'000003': '请重新登录',/令牌无效 */'000004': '请重新登录',/非法请求 */'000005': '非法请求',/参数非法 */'000006': '参数非法',/参数为空 */'000007': '数据为空',
};/关于业务逻辑上的响应码 */
export const BusinessResponseCode = {/账号不存在 */'000101': '账号信息有误,请确认',/图片验证码不一致 */'000102': '图片验证码有误',/短信验证码不一致 */'000103': '短信验证码错误',/与保单绑定的手机号不一致 */'000104': '手机号有误,请确认',/未勾选同意条款 */'000105': '请先勾选保单设计须知。',/短信验证码获取频繁 */'000106': '短信验证码获取频繁',/修改保单失败 */'000107': '修改失败',/添加保单信息失败 */'000108': '添加保单信息失败',/保单已存在 */'000109': '保单已存在',/内部错误 */'000110': '内部错误',/保单设计已完成 */'000111': '保单设计已完成',/获取图片信息失败 */'000112': '获取图片失败,请刷新重试','000113': '图片保存失败,请重试','000114': '上传文件过大,请重新上传','000115': '文件上传失败,请重新上传','000116': '已参加该活动','000117': '活动已结束','000118': '参加的活动不存在',
};/请求状态 */
export const RequestStu = {/ 请求成功 */success: 'success',/ 请求错误 */error: 'error',/ 连接失败 */networkError: 'networkError',
};
2,使用
1,比如有一个登陆接口 ;我们需要封装一下:
import { myAxios } from '../myAxios';
const prefix = '/backend'
export default {/* 请求登录接口 get请求 普通的get请求和post请求 */queryLogin(mobileNo) {return myAxios.get(`${prefix}/api/user/login`, mobileNo);},
};
2,然后再vue组件中请求这个接口:
methods: {async handleLogin() {// 非空判断if (!this.loginForm.account || !this.loginForm.password) {return this.$message('账号或者密码不能为空!');}// 调用此接口 解构数据const { isSuccess, data, code } = await api.login.queryLogin({account: 'xinjie1',password: '123456789',});// 请求失败的处理if (!isSuccess) {return this.$message({ type: 'error', message: code });}// 请求成功的处理 dataconsole.log(data)....}}
3,vue配置接口代理,解决开发环境中的跨域问题;vue.config.js配置如下:
// 服务端ip 需要代理的地址
const api = 'http://10.11.12.181:26341';/* 开发环境跨域情况的代理配置 */devServer: {/* 接口代理器设置 可以配置多个*/proxy: {'/backend': {// 实际访问的服务器地址target: api,// 控制服务器收到的请求头中Host字段的值 host就是主机名加端口号 实际上就是欺骗后端服务器changeOrigin: true,// 是否启用websocketsws: false,// 重写请求路径 开头是/api的替换为 空串pathRewrite: { '/api': '' },},},},
4,如果是上传文件,需要使用formData,接口封装需要处理一下:
import { myAxios } from '../myAxios';
const prefix = '/backend'
export default {/* formData 文件上传 */uploadImg(policyId, policyNo, file) {const formData = new FormData();formData.append('policyId', policyId.toString());formData.append('policyNo', policyNo);formData.append('uploadFile', file);// 添加文件上传的请求头const axiosConfig = {headers: {'Content-Type': 'multipart/form-data',},timeout: 10000, //超时时间// 表示允许在向服务器发送前,修改请求数据transformRequest: [function (data, headers) {return data;},],};return myAxios.post(`${prefix}/api/user/uploadImg`, formData, { axiosConfig: axiosConfig });},
}