转载地址:https://juejin.im/post/5a02a898f265da43052e0c85
1、背景
- 在项目开发中ajax请求是必不可缺少
- 一部分ajax请求不需要loading或则请求时间少于多少是不显示loading
- 项目中对请求的同一化处理(错误处理,返回数据格式化处理,loading处理,token处理)
- 配置基于个人vue项目进行配置,已加载vux相关组件,会进行一些依赖的import(可以按需配置)
1 import Vue from 'vue' 2 import axios from 'axios' 3 //项目的一些环境配置参数,读取host 4 import config from '@/config' 5 //vuex状态管理,这里主要进行对全局loading的控制 6 import store from '@/store' 7 //vue-router对相应状态码的页面操作(router实例) 8 import router from '@/router' 9 //console对应封装 10 import { log } from '@/utils'
2、解决方案
对于axios的封装中我们定义几个参数进行申明
1 // 加载最小时间 2 const MINI_TIME = 300 3 // 超时时间(超时时间) 4 let TIME_OUT_MAX = 5000 5 // 环境value 6 let _env = process.env.NODE_ENV 7 // 请求接口host 8 let _apiHost = config.api 9 // 请求组(判断当前请求数) 10 let _requests = []
一般一个项目中的根host和Content-Type都是统一的,这里对axios进行统一的配置(如果这个后端需要formData格式的表单即content-type='application/x-www-form-urlencoded;charset=utf-8'数据,需要对请求数据进行表单序列化,比较快的方式就是引入qs库qs.stringify进行处理后传输)
1 axios.defaults.headers.common['Content-Type'] = 'application/json' 2 axios.defaults.baseURL = _apiHost
一般情况下项目中同一时刻都会有不止一个请求在进行(还没有返回),要判断当前是否还存在进行中的ajax,就需要对_requests这个数组进行维护;
1 /** 2 * 添加请求,显示loading 3 * @param {请求配置} config 4 */ 5 function pushRequest(config) { 6 log(`${config.url}--begin`) 7 _requests.push(config) 8 Vue.$vux.loading.show({ 9 text: 'Loading' 10 }) 11 store.dispatch('loading') 12 } 13 14 /** 15 * 移除请求,无请求时关闭loading 16 * @param {请求配置} config 17 */ 18 function popRequest(config) { 19 log(`${config.url}--end`) 20 let _index = _requests.findIndex(r => { 21 return r === config 22 }) 23 if (_index > -1) { 24 _requests.splice(_index, 1) 25 } 26 if (!_requests.length) { 27 Vue.$vux.loading.hide(0) 28 store.dispatch('loading', false) 29 } 30 } 31 接下来对axios基于上面的准备进行处理 32 33 /** 34 * 请求地址,请求数据,是否静默,请求方法 35 */ 36 export default (url, data = {}, isSilence = false, method = 'POST') => { 37 let _opts = { method, url } 38 //通用数据的合并(token) 39 let _data = Object.assign({}, data, { token: store.getters.token }) 40 const _query = {} 41 for (let _key in _data) { 42 if (_data.hasOwnProperty(_key) && _data[_key] !== '') { 43 _query[_key] = _data[_key] 44 } 45 } 46 //axios实例请求定时器ID 47 let _timer = null 48 //判断请求类型 49 if (method.toLocaleUpperCase() === 'POST') { 50 _opts.data = _query 51 } else { 52 _opts.params = _query 53 } 54 //返回一个promise 55 return new Promise((resolve, reject) => { 56 //实例化axios 57 const _instance = axios.create({ 58 timeout: TIME_OUT_MAX 59 }) 60 //定义请求的唯一标识 61 let _random = { stamp: Date.now(), url: `${_apiHost + url}` } 62 //判断是否静默(静默的话就不加入请求标识队列,不是则申明此请求实例的定时器) 63 if (!isSilence) { 64 _timer = setTimeout(() => { 65 pushRequest(_random) 66 }, MINI_TIME) 67 } 68 //axios实例发送当前请求 69 //请求完成:1、取消当前请求的定时器;2、在当前请求标识队列中移除当前标识; 70 3、成功的话返回统一处理后的数据,失败则对状态码进行判断 71 _instance(_opts) 72 .then(res => { 73 let responseData = res.data 74 clearTimeout(_timer) 75 popRequest(_random) 76 resolve(res.data) 77 }) 78 .catch(res => { 79 let _response = res.response 80 let _message = null 81 clearTimeout(_timer) 82 popRequest(_random) 83 switch (_response.status) { 84 case 404: 85 _message = '404,错误请求' 86 break 87 case 401: 88 router.push({ path: '/login', query: { redirect: router.currentRoute.fullPath } }) 89 _message = '未授权' 90 break 91 case 403: 92 _message = '禁止访问' 93 break 94 case 408: 95 _message = '请求超时' 96 break 97 case 500: 98 _message = '服务器内部错误' 99 break 100 case 501: 101 _message = '功能未实现' 102 break 103 case 503: 104 _message = '服务不可用' 105 break 106 case 504: 107 _message = '网关错误' 108 break 109 default: 110 _message = '未知错误' 111 } 112 if (!isSilence) { 113 Vue.$vux.toast.show({ 114 text: _response.data && _response.data.error ? _response.data.error : _message, 115 type: 'warn', 116 '10em' 117 }) 118 } 119 reject(res) 120 }) 121 }) 122 }
作者:NoManReady
链接:https://juejin.im/post/5a02a898f265da43052e0c85
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。