/** * @description: axios封装 - 请求拦截、相应拦截、错误统一处理 * @param {*} * @return {*} */ import axios from 'axios'; import { Loading, Message } from 'element-ui'; import store from "../store"; import _ from 'lodash'; import router from "../router"; import qs from "qs"; import projectConfig from "./projectConfig"; // loading对象 let loadingInstance; // 请求合并只出现一次loading // 当前正在请求的数量 let loadingRequestCount = 0; // 请求超时时间 axios.defaults.timeout = 10000; //创建一个axios 实例 const service = axios.create({ // baseURL: projectConfig.netHost, // baseURL: 'https://lz.dev.trydotec.com:8416/miniapp', timeout: 30000, }); // 请求拦截器 service.interceptors.request.use( config => { let loadingTarget = '#app'; // console.log('request拦截器config参数:', config) if(config.loadingTarget){ loadingTarget = config.loadingTarget } let target = document.querySelector(loadingTarget); if(target && !config.hideLoading){ // 请求拦截进来调用显示loading效果,默认都有loading效果 showLoading(loadingTarget); } let token = sessionStorage.getItem('token') // console.log('获取token',token) // let token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI2M2Q1OTYxZi1mMTYzLTRjMWYtYjJkYy1iMzFiMjQ5YzA3ZTMiLCJpYXQiOjE2NjE5MjgzODEsImlzcyI6ImFkbWluIiwiYXVkIjoiMiIsInBsYXlsb2FkIjp7ImFyZWFDb2RlIjpudWxsLCJ0ZW5hbnRLZXkiOiJ0ZW5hbnQtMDAwMSIsImRlcHRJZCI6IjEiLCJkaWdlc3QiOm51bGwsIm5hbWUiOiIlRTclOTQlOTglRTclQjQlQTAlRTclOEYlOEQiLCJ1c2VySWQiOiIyIiwidXNlcm5hbWUiOiJnYW5zdXpoZW4ifSwiZXhwIjoxNjYyNjEyMzgxfQ.3GeuL01sIJ6JLbJr4rIz8lHJdtjZVDf9y4hMh_p0If8' // 身份令牌 token && (config.headers['Authorization'] = token) return config; }, (error) => { hideLoading() Promise.error(error) } ) // 响应拦截器 service.interceptors.response.use( response => { setTimeout(() => { hideLoading() }, 200); console.log('请求返回结果:', response) // 处理Blob格式的数据 const res = response.data if(res instanceof Blob) { return new Promise((resolve, reject) => { const reader = new FileReader() reader.readAsText(res) reader.onload = (e) => { const { result } = e.target if (result.code) { // todo 此处,需要统一对错误做处理 // Message.closeAll() // Message({ message: result.message, showClose: true, type: "error" }) reject(dealResponseError(result)) } else { resolve(response) console.log('请求返回结果11111:', response) } } }) }else if(res.code) { return new Promise((resolve, reject) => { if(res.code === 9200) { resolve(res.data) }else{ // todo 此处,需要统一对错误做处理 reject(dealResponseError(res)); } }) } // return Promise.resolve(response.data); }, error => { console.log('请求报错:', error) // todo 此处,需要统一对错误做处理 if(error.response.status == 401) { Message.closeAll() setTimeout(() => { hideLoading() }, 200); // 登录过期&token存在,此时有提示 Message({ message: '请求要求用户的身份认证', type: "error",customClass:'messageZindex'}) store.state.token = ''; sessionStorage.removeItem('token'); sessionStorage.removeItem('userInfo'); store.state.userinfo = {}; store.state.routes = []; setTimeout(() => { router.push('/login') }, 300) } else { Message.closeAll() Message.error(`请求错误: ${error}`) setTimeout(() => { hideLoading() }, 200); if(error.response.status) { return Promise.reject(error.response); } } } ); // 显示loading的函数 并且记录请求次数 ++ const showLoading = (target) => { if(loadingRequestCount === 0) { loadingInstance = Loading.service({ lock: true, text: '加载中...', target: target || 'body' }); } loadingRequestCount++; } // 隐藏loading的函数,并且记录请求次数 const hideLoading = () => { if(loadingRequestCount <= 0) return; loadingRequestCount--; if(loadingRequestCount === 0) { toHideLoading(); } } // 防抖:将 300ms 间隔内的关闭 loading 便合并为一次. 防止连续请求时, loading闪烁的问题。 var toHideLoading = _.debounce(() => { loadingInstance.close(); loadingInstance = null; }, 300); const dealResponseError = (error) => { let code = error.code ||'' let msg = error.msg || '' switch (code) { case 9400: break; case 9401: msg = "当前登录已失效,请重新登录!" break; case 9403: msg = "登陆令牌失效!" break; case 400: msg = "客户端请求的语法错误,服务器无法理解!" break; case 401: msg = "请求要求用户的身份认证!" break; case 403: msg = "服务器理解请求客户端的请求,但是拒绝执行此请求!" break; case 404: msg = "找不到资源(网页)!" break; case 405: msg = "客户端请求中的方法被禁止!" break; case 500: case 9500: msg = "服务器内部错误,无法完成请求!" break; case 503: msg = "充当网关或代理的服务器,未及时从远端服务器获取请求!" break; default: msg = "网络出错!"; break; } console.log('错误处理----code:', code, '----msg----:', msg) Message.closeAll() // todo 不知道能否预防多个请求都返回登录失效的情况,提示只有1个 if((code == 9401 || code == 9403) && store.state.token) { // 登录过期&token存在,此时有提示 Message({ message: msg, type: "error",customClass:'messageZindex' }) store.state.token = ''; sessionStorage.removeItem('token'); sessionStorage.removeItem('userInfo'); store.state.userinfo = {}; store.state.routes = []; setTimeout(() => { router.push('/login') }, 300) }else{ Message({ message: msg, type: "error",customClass:'messageZindex'}) } let errorInfo = new Error(msg) errorInfo.code = code return errorInfo } // /** // * post方法,对应post请求 // * @param {String} url [请求的url地址] // * @param {Object} params [请求时携带的参数] // */ // export function post (url, params) { // return new Promise((resolve, reject) => { // axios.post(url, QS.stringify(params)) // .then(res => { // resolve(res.data); // }) // .catch(err => { // reject(err.data) // }) // }); // } // // /** // * get方法,对应get请求 // * @param {String} url [请求的url地址] // * @param {Object} params [请求时携带的参数] // */ // export function get (url, param) { // return new Promise((resolve, reject) => { // axios.get(url, { params: params }) // .then(response => { // resolve(response.data) // }, err => { // reject(err) // }) // .catch((error) => { // reject(error) // }) // }) // } const download = (url, method = "get", param, customConfig) => { let obj = {}; if (method === "get") { obj.params = param; } else { obj.data = param; } return new Promise((resolve, reject) => { service({ method: method, url, ...obj, responseType: "blob", }) .then((res) => { resolve(res); }) .catch((error) => { reject(error); }); }); }; // export default service export default { service, postFile: (url, param, customConfig) =>download(url, "post", param, customConfig), }