responseInterceptors.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. let param = {}
  36. let refreshToken = uni.getStorageSync('REFRESH_TOKEN');
  37. param.refreshToken = refreshToken;
  38. const refreshTokenRes = await refreshToken(param)
  39. // 2.1 刷新成功,则回放队列的请求 + 当前请求
  40. vm.$store.commit('SET_TOKEN', refreshTokenRes.data)
  41. requestList.forEach(cb => cb())
  42. return uni.$u.http.request(res.config)
  43. } catch (e) {
  44. // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
  45. // 2.2 刷新失败,只回放队列的请求
  46. requestList.forEach(cb => cb())
  47. // 登出。即不回放当前请求!不然会形成递归
  48. vm.$store.commit('CLEAR_LOGIN_INFO')
  49. return Promise.reject(res)
  50. } finally {
  51. requestList = []
  52. isRefreshToken = false
  53. }
  54. } else {
  55. // 添加到队列,等待刷新获取到新的令牌
  56. return new Promise(resolve => {
  57. requestList.push(() => {
  58. res.config.header.Authorization = 'Bearer ' + vm.$store.getters.accessToken // 让每个请求携带自定义token 请根据实际情况自行修改
  59. resolve(uni.$u.http.request(res.config))
  60. })
  61. })
  62. }
  63. } else if (code === 500) {
  64. uni.$u.toast(msg)
  65. return Promise.reject(res)
  66. } else if (code === 901) {
  67. uni.$u.toast('演示模式,无法进行写操作')
  68. return Promise.reject(res)
  69. } else if (code !== 0) {
  70. if (msg === '无效的刷新令牌') {
  71. // hard coding:忽略这个提示,直接登出
  72. console.log(msg)
  73. } else {
  74. uni.$u.toast(msg)
  75. }
  76. return Promise.reject(res)
  77. } else {
  78. return res.data
  79. }
  80. },
  81. err => {
  82. console.log(err)
  83. let { message } = err
  84. if (!message) {
  85. message = '系统发生未知错误'
  86. }else if (message === 'Network Error') {
  87. message = '后端接口连接异常'
  88. } else if (message.includes('timeout')) {
  89. message = '系统接口请求超时'
  90. } else if (message.includes('Request failed with status code')) {
  91. message = '系统接口' + message.substring(message.length - 3) + '异常'
  92. }
  93. uni.$u.toast(message)
  94. return Promise.reject(err)
  95. }
  96. )
  97. }