responseInterceptors.js 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import errorCode from '@/utils/request/errorCode'
  2. import { refreshToken } from '@/api/auth'
  3. // 需要忽略的提示。忽略后,自动 Promise.reject('error')
  4. const ignoreMsgs = [
  5. '无效的刷新令牌', // 刷新令牌被删除时,不用提示
  6. '刷新令牌已过期' // 使用刷新令牌,刷新获取新的访问令牌时,结果因为过期失败,此时需要忽略。否则,会导致继续 401,无法跳转到登出界面
  7. ]
  8. // 请求队列
  9. let requestList = []
  10. // 是否正在刷新中
  11. let isRefreshToken = false
  12. /**
  13. * 响应拦截
  14. * @param {Object} http
  15. */
  16. module.exports = vm => {
  17. uni.$u.http.interceptors.response.use(
  18. async res => {
  19. const code = res.data.code || 0
  20. const msg = res.data.msg || errorCode[code] || errorCode['default']
  21. if (ignoreMsgs.indexOf(msg) !== -1) {
  22. // 如果是忽略的错误码,直接返回 msg 异常
  23. return Promise.reject(msg)
  24. } else if (code === 401) {
  25. // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
  26. if (!isRefreshToken) {
  27. isRefreshToken = true
  28. // 1. 如果获取不到刷新令牌,则只能执行登出操作
  29. if (!vm.$store.getters.refreshToken()) {
  30. vm.$store.commit('CLEAR_LOGIN_INFO')
  31. return Promise.reject(res)
  32. }
  33. // 2. 进行刷新访问令牌
  34. try {
  35. const refreshTokenRes = await refreshToken()
  36. // 2.1 刷新成功,则回放队列的请求 + 当前请求
  37. vm.$store.commit('SET_TOKEN', refreshTokenRes.data)
  38. requestList.forEach(cb => cb())
  39. return uni.$u.http.request(res.config)
  40. } catch (e) {
  41. // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
  42. // 2.2 刷新失败,只回放队列的请求
  43. requestList.forEach(cb => cb())
  44. // 登出。即不回放当前请求!不然会形成递归
  45. vm.$store.commit('CLEAR_LOGIN_INFO')
  46. return Promise.reject(res)
  47. } finally {
  48. requestList = []
  49. isRefreshToken = false
  50. }
  51. } else {
  52. // 添加到队列,等待刷新获取到新的令牌
  53. return new Promise(resolve => {
  54. requestList.push(() => {
  55. res.config.header.Authorization = 'Bearer ' + vm.$store.getters.accessToken // 让每个请求携带自定义token 请根据实际情况自行修改
  56. resolve(uni.$u.http.request(res.config))
  57. })
  58. })
  59. }
  60. } else if (code === 500) {
  61. uni.$u.toast(msg)
  62. return Promise.reject(res)
  63. } else if (code === 901) {
  64. uni.$u.toast('演示模式,无法进行写操作')
  65. return Promise.reject(res)
  66. } else if (code !== 0) {
  67. if (msg === '无效的刷新令牌') {
  68. // hard coding:忽略这个提示,直接登出
  69. console.log(msg)
  70. } else {
  71. uni.$u.toast(msg)
  72. }
  73. return Promise.reject(res)
  74. } else {
  75. return res.data
  76. }
  77. },
  78. err => {
  79. console.log(err)
  80. let { message } = err
  81. if (!message) {
  82. message = '系统发生未知错误'
  83. }else if (message === 'Network Error') {
  84. message = '后端接口连接异常'
  85. } else if (message.includes('timeout')) {
  86. message = '系统接口请求超时'
  87. } else if (message.includes('Request failed with status code')) {
  88. message = '系统接口' + message.substring(message.length - 3) + '异常'
  89. }
  90. uni.$u.toast(message)
  91. return Promise.reject(err)
  92. }
  93. )
  94. }