ajax.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // ajax.js
  2. // 引入 uni-ajax 模块
  3. import ajax from 'uni-ajax'
  4. import store from '@/store'
  5. // 错误log上传
  6. function errorApiLogUpload(response) {
  7. const code = response?.data?.code || ''
  8. const isLog = response?.config?.header?.isLog // 上报问题接口
  9. if (!isLog && code && code !== 200) {
  10. const url = response?.config?.url
  11. console.log('errorApiLogUpload', url, code, response)
  12. const content = '【前端接口日志】:' + JSON.stringify(response)
  13. instance.post('/shunt/proposal-apply', {
  14. content
  15. }, {
  16. header: {
  17. // 避免死循环
  18. isLog: 1,
  19. // 上传log 专属token
  20. token: 'eyJhbGciOiJIUzUxMiJ9.eyJ5ZWFySWQiOiIyMDIyIiwiY29sbGVnZUlkIjotMSwic3R1ZGVudE5vIjoiLTEiLCJpc3N1ZXIiOiJzaHVudCBhdXRoIEpXVCBJc3N1ZXIgMS4wIiwiZXhwIjozNzY1NDEzMDU3Mn0.9OkmMbwt7tFRdgOopNVPYCq0VNXE-f-Y-yv57kfRZQDjDy_THGvsu_UQyOyGkgV9d8WoPklagBB5K2Bbj5OFdA'
  21. }
  22. })
  23. }
  24. }
  25. // 创建请求实例
  26. const instance = ajax.create({
  27. // 初始配置
  28. baseURL: '',
  29. timeout: 6000,
  30. // responseType: 'json',
  31. // withCredentials: true
  32. })
  33. /* 无感刷新 Token */
  34. let isRefreshing = false // 当前是否在请求刷新 Token
  35. let requestQueue = [] // 将在请求刷新 Token 中的请求暂存起来,等刷新 Token 后再重新请求
  36. // 执行暂存起来的请求
  37. const executeQueue = error => {
  38. requestQueue.forEach(promise => {
  39. if (error) {
  40. promise.reject(error)
  41. } else {
  42. promise.resolve()
  43. }
  44. })
  45. requestQueue = []
  46. }
  47. // 刷新 Token 请求
  48. const refreshToken = () => instance.post('/shunt/login', {
  49. code: uni.getStorageSync('code')
  50. })
  51. // 刷新 Token 请求处理,参数为刷新成功后的回调函数
  52. const refreshTokenHandler = afresh => {
  53. // 如果当前是在请求刷新 Token 中,则将期间的请求暂存起来
  54. if (isRefreshing) {
  55. return new Promise((resolve, reject) => {
  56. requestQueue.push({
  57. resolve,
  58. reject
  59. })
  60. }).then(afresh)
  61. }
  62. isRefreshing = true
  63. return new Promise((resolve, reject) => {
  64. uni.showLoading({
  65. title: '登录中',
  66. mask: true
  67. })
  68. let token = ''
  69. store.commit('user/setToken', token)
  70. refreshToken()
  71. .then(res => {
  72. errorApiLogUpload(res)
  73. token = res?.data?.token || ''
  74. // if (token) {
  75. // uni.setStorageSync('TOKEN', token)
  76. // resolve(afresh?.())
  77. // executeQueue(null)
  78. // } else {
  79. // return Promise.reject(res)
  80. // }
  81. })
  82. .catch(err => {
  83. // uni.removeStorageSync('TOKEN')
  84. // reject(err)
  85. // executeQueue(err)
  86. console.error('login', error)
  87. })
  88. .finally(() => {
  89. isRefreshing = false
  90. uni.hideLoading()
  91. store.commit('user/setToken', token)
  92. if (token) {
  93. store.dispatch('user/updateUserInfo')
  94. // 重新获取接口的话 旧的接口会保留问题token,导致登录死循环
  95. // setTimeout(() => {
  96. // resolve(afresh?.())
  97. // executeQueue(null)
  98. // }, 5000)
  99. uni.reLaunch({
  100. url: '/pages/index/index'
  101. });
  102. } else {
  103. store.commit('user/logout', '')
  104. uni.reLaunch({
  105. url: '/pages/error/403/403'
  106. });
  107. reject(err)
  108. executeQueue(err)
  109. }
  110. })
  111. })
  112. }
  113. // 添加请求拦截器
  114. instance.interceptors.request.use(
  115. config => {
  116. // 给每条请求赋值 Token 请求头
  117. config.header['token'] = config.header['token'] || store.state.user.token || uni.getStorageSync(
  118. 'TOKEN') // token令牌
  119. const requestUid = new Date().getTime() // 请求requestUid,时间戳
  120. config.data = {
  121. data: Object.assign({}, config?.data || {}),
  122. requestUid
  123. }
  124. // 在发送请求前做些什么
  125. return config
  126. },
  127. error => {
  128. // 对请求错误做些什么
  129. return Promise.reject(error)
  130. }
  131. )
  132. // 添加响应拦截器
  133. instance.interceptors.response.use(
  134. response => {
  135. if (response?.config?.header?.isLog) { // 上报问题接口 无需处理
  136. return
  137. }
  138. errorApiLogUpload(response)
  139. const {
  140. code,
  141. data,
  142. msg
  143. } = response.data || {}
  144. if (code === 200) {
  145. return response.data
  146. } else if (code === 201 || code === 202 || code === 203) { // 刷新 Token
  147. store.commit('user/logout', '')
  148. uni.reLaunch({
  149. url: '/pages/error/403/403'
  150. });
  151. return Promise.reject(response.data)
  152. // return refreshTokenHandler(() => instance(response.config))
  153. } else {
  154. msg && uni.showToast({
  155. title: msg,
  156. position: 'top',
  157. icon: 'none',
  158. duration: 2500
  159. });
  160. return Promise.reject(response.data)
  161. }
  162. },
  163. error => {
  164. // 对响应错误做些什么
  165. return Promise.reject(error)
  166. }
  167. )
  168. // 导出 create 创建后的实例
  169. export default instance
  170. // 200=成功时状态码
  171. // 201=token超时
  172. // 202=token为空
  173. // 203=token非法
  174. // 402=业务数据配置缺失时错误码
  175. // 403=超出服务范围时,禁止提供服务(熔断,高并发限流)时,错误码
  176. // 500=未定义的系统异常(Exception)时,错误码
  177. // 401=业务未授权时进行访问,401(权限校验)
  178. // 402=方法参数错误