1、前端网络请求封装、异常统一处理
vue中采用axios处理网络请求,避免请求接口重复代码,以及各种网络情况造成的异常情况的判断,采用axios请求封装和异常拦截操作;
axios 请求封装
// 引入axios文件包
import axios from 'axios' // POST 方法封装 (参数处理) export const postRequest = (url, params) => { return axios({ method: 'post', url: url, data: params, transformRequest: [function (data) { let ret = '' for (let it in data) { ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&' } return ret }], headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); } // POST 方法封装 (文件上传) export const uploadFileRequest = (url, params) => { return axios({ method: 'post', url: url, data: params, headers: { 'Content-Type': 'multipart/form-data' } }); } // GET 方法封装 export const getRequest = (url) => { return axios({ method: 'get', url: url }); } // PUT 方法封装 export const putRequest = (url, params) => { return axios({ method: 'put', url: url, data: params, transformRequest: [function (data) { let ret = '' for (let it in data) { ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&' } return ret }], headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); } // DELETE 方法封装 export const deleteRequest = (url) => { return axios({ method: 'delete', url: url }); }
2)axios请求异常统一处理
// 引入依赖包
import axios from 'axios' import {Message} from 'element-ui' // REQUEST 请求异常拦截 axios.interceptors.request.use(config=> { //========== 所有请求之前都要执行的操作 ============== return config; }, err=> { //================== 错误处理 ==================== Message.error({message: '请求超时!'}); return Promise.resolve(err); }) // RESPONSE 响应异常拦截 axios.interceptors.response.use(data=> { //============== 所有请求完成后都要执行的操作 ================== // 第一种方式 // 根据返回的code值来做不同的处理(和后端约定) switch (data.code) { case '0': // exp: 修复iPhone 6+ 微信点击返回出现页面空白的问题 if (isIOS()) { // 异步以保证数据已渲染到页面上 setTimeout(() => { // 通过滚动强制浏览器进行页面重绘 document.body.scrollTop += 1 }, 0) } // 这一步保证数据返回,如果没有return则会走接下来的代码,不是未登录就是报错 return data // 需要重新登录 case 'SHIRO_E5001': // 微信生产环境下授权登录 if (isWeChat() && IS_PRODUCTION) { axios.get(apis.common.wechat.authorizeUrl).then(({ result }) => { location.replace(global.decodeURIComponent(result)) }) } else { // 否则跳转到h5登录并带上跳转路由 const search = encodeSearchParams({ next: location.href, }) location.replace(`/user/login`) } // 不显示提示消息 data.description = '' break default: } // 若不是正确的返回code,且已经登录,就抛出错误 const err = new Error(data.description) err.data = data err.response = response // 第二种方式,仅对200和error状态处理 if (data.status && data.status == 200 && data.data.status == 'error') { Message.error({message: data.data.msg}); return; } return data; }, err=> { //============== 错误处理 ==================== if (err && err.response) { switch (err.response.status) { case 400: err.message = '请求错误(400)'; break; case 401: err.message = '未授权,请重新登录(401)'; break; case 403: err.message = '拒绝访问(403)'; break; case 404: err.message = '请求出错(404)'; break; case 408: err.message = '请求超时(408)'; break; case 500: err.message = '服务器错误(500)'; break; case 501: err.message = '服务未实现(501)'; break; case 502: err.message = '网络错误(502)'; break; case 503: err.message = '服务不可用(503)'; break; case 504: err.message = '网络超时(504)'; break; case 505: err.message = 'HTTP版本不受支持(505)'; break; default: err.message = `连接出错(${err.response.status})!`; } } else { err.message = '连接服务器失败!' } Message.err( {message: err.message } ) return Promise.resolve(err); })
请求出错的时候我执行的是:Promise.resolve(err);,而不是Promise.reject(err);,这样无论请求成功还是失败,在成功的回调中都能收到通知
2、VUE 项目中使用该方法
1)在main.js中导入所有请求方法
// 导入所有请求方法
import {getRequest} from './utils/api' import {postRequest} from './utils/api' import {deleteRequest} from './utils/api' import {putRequest} from './utils/api'
2)将请求方法添加至 Vue.prototype 上
// 向VUE的原型上添加请求方法
Vue.prototype.getRequest = getRequest;
Vue.prototype.postRequest = postRequest;
Vue.prototype.deleteRequest = deleteRequest;
Vue.prototype.putRequest = putRequest;
3)发送请求(请求方法的调用)
// 发送网络请求
this.postRequest('/login', {userName,password}).then(resp=> { ... } });
4)案例
import Vue from 'vue'
import cypressIndex from '../components/rootVue/cypressIndex' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; // axios请求的方法引入 import {getRequest} from '../components/utils/settings' import {postRequest} from '../components/utils/settings' Vue.use(ElementUI); // 将axios方法添加到VUE原型上 Vue.prototype.getRequest = getRequest; Vue.prototype.postRequest = postRequest; Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#cypressIndex', render: h => h(cypressIndex) })