// ajax.js // 引入 uni-ajax 模块 import ajax from 'uni-ajax' import store from '@/store' // 错误log上传 function errorApiLogUpload(response) { const code = response?.data?.code || '' const isLog = response?.config?.header?.isLog // 上报问题接口 if (!isLog && code && code !== 200) { const url = response?.config?.url console.log('errorApiLogUpload', url, code, response) const content = '【前端接口日志】:' + JSON.stringify(response) instance.post('/shunt/proposal-apply', { content }, { header: { // 避免死循环 isLog: 1, // 上传log 专属token token: 'eyJhbGciOiJIUzUxMiJ9.eyJ5ZWFySWQiOiIyMDIyIiwiY29sbGVnZUlkIjotMSwic3R1ZGVudE5vIjoiLTEiLCJpc3N1ZXIiOiJzaHVudCBhdXRoIEpXVCBJc3N1ZXIgMS4wIiwiZXhwIjozNzY1NDEzMDU3Mn0.9OkmMbwt7tFRdgOopNVPYCq0VNXE-f-Y-yv57kfRZQDjDy_THGvsu_UQyOyGkgV9d8WoPklagBB5K2Bbj5OFdA' } }) } } // 创建请求实例 const instance = ajax.create({ // 初始配置 baseURL: '', timeout: 6000, // responseType: 'json', // withCredentials: true }) /* 无感刷新 Token */ let isRefreshing = false // 当前是否在请求刷新 Token let requestQueue = [] // 将在请求刷新 Token 中的请求暂存起来,等刷新 Token 后再重新请求 // 执行暂存起来的请求 const executeQueue = error => { requestQueue.forEach(promise => { if (error) { promise.reject(error) } else { promise.resolve() } }) requestQueue = [] } // 刷新 Token 请求 const refreshToken = () => instance.post('/shunt/login', { code: uni.getStorageSync('code') }) // 刷新 Token 请求处理,参数为刷新成功后的回调函数 const refreshTokenHandler = afresh => { // 如果当前是在请求刷新 Token 中,则将期间的请求暂存起来 if (isRefreshing) { return new Promise((resolve, reject) => { requestQueue.push({ resolve, reject }) }).then(afresh) } isRefreshing = true return new Promise((resolve, reject) => { uni.showLoading({ title: '登录中', mask: true }) let token = '' store.commit('user/setToken', token) refreshToken() .then(res => { errorApiLogUpload(res) token = res?.data?.token || '' // if (token) { // uni.setStorageSync('TOKEN', token) // resolve(afresh?.()) // executeQueue(null) // } else { // return Promise.reject(res) // } }) .catch(err => { // uni.removeStorageSync('TOKEN') // reject(err) // executeQueue(err) console.error('login', error) }) .finally(() => { isRefreshing = false uni.hideLoading() store.commit('user/setToken', token) if (token) { store.dispatch('user/updateUserInfo') // 重新获取接口的话 旧的接口会保留问题token,导致登录死循环 // setTimeout(() => { // resolve(afresh?.()) // executeQueue(null) // }, 5000) uni.reLaunch({ url: '/pages/index/index' }); } else { store.commit('user/logout', '') uni.reLaunch({ url: '/pages/error/403/403' }); reject(err) executeQueue(err) } }) }) } // 添加请求拦截器 instance.interceptors.request.use( config => { // 给每条请求赋值 Token 请求头 config.header['token'] = config.header['token'] || store.state.user.token || uni.getStorageSync( 'TOKEN') // token令牌 const requestUid = new Date().getTime() // 请求requestUid,时间戳 config.data = { data: Object.assign({}, config?.data || {}), requestUid } // 在发送请求前做些什么 return config }, error => { // 对请求错误做些什么 return Promise.reject(error) } ) // 添加响应拦截器 instance.interceptors.response.use( response => { if (response?.config?.header?.isLog) { // 上报问题接口 无需处理 return } errorApiLogUpload(response) const { code, data, msg } = response.data || {} if (code === 200) { return response.data } else if (code === 201 || code === 202 || code === 203) { // 刷新 Token store.commit('user/logout', '') uni.reLaunch({ url: '/pages/error/403/403' }); return Promise.reject(response.data) // return refreshTokenHandler(() => instance(response.config)) } else { msg && uni.showToast({ title: msg, position: 'top', icon: 'none', duration: 2500 }); return Promise.reject(response.data) } }, error => { // 对响应错误做些什么 return Promise.reject(error) } ) // 导出 create 创建后的实例 export default instance // 200=成功时状态码 // 201=token超时 // 202=token为空 // 203=token非法 // 402=业务数据配置缺失时错误码 // 403=超出服务范围时,禁止提供服务(熔断,高并发限流)时,错误码 // 500=未定义的系统异常(Exception)时,错误码 // 401=业务未授权时进行访问,401(权限校验) // 402=方法参数错误