request.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /**
  2. * 网络请求配置
  3. */
  4. import { PendingType, ResponseData } from '@/types/request'
  5. import CONSTS from '@/utils/consts'
  6. import history from '@/utils/history'
  7. import { storage } from '@/utils/util'
  8. import { message } from 'antd'
  9. import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
  10. const pending: Array<PendingType> = []
  11. const removePending = (config: AxiosRequestConfig) => {
  12. for (const key in pending) {
  13. const item: number = +key
  14. const list: PendingType = pending[key]
  15. // 当前请求在数组中存在时执行函数体
  16. if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
  17. // 执行取消操作
  18. list.cancel('操作太频繁,请稍后再试')
  19. // 从数组中移除记录
  20. pending.splice(item, 1)
  21. }
  22. }
  23. }
  24. const service = axios.create({
  25. baseURL: process.env.NODE_ENV === 'development' ? CONSTS.BASE_URL.DEV : CONSTS.BASE_URL.PROD,
  26. timeout: 5000,
  27. withCredentials: true
  28. })
  29. /**
  30. * request 拦截器
  31. */
  32. service.interceptors.request.use(
  33. request => {
  34. removePending(request)
  35. request.cancelToken = new axios.CancelToken(func => {
  36. pending.push({ url: request.url, method: request.method, params: request.params, data: request.data, cancel: func })
  37. })
  38. if (request?.method !== 'get') {
  39. request.headers['X-CSRF-Token'] = storage.get('csrf_token')
  40. }
  41. return request
  42. },
  43. err => {
  44. console.log(err)
  45. return Promise.reject(err)
  46. }
  47. )
  48. /**
  49. * response 拦截器
  50. */
  51. service.interceptors.response.use(
  52. (response: AxiosResponse) => {
  53. removePending(response.config)
  54. const data: ResponseData = response.data
  55. // 对Code不等于Success进行message提示
  56. if (data.code !== CONSTS.RET_CODE.SUCCESS) {
  57. message.error(data.msg)
  58. switch (data.code) {
  59. case 1:
  60. history.push('/login')
  61. break
  62. default:
  63. break
  64. }
  65. }
  66. if (response.config.method?.toLocaleUpperCase() === 'GET') {
  67. const token = response?.headers['x-csrf-token']
  68. storage.set('csrf_token', token)
  69. }
  70. return response
  71. },
  72. error => {
  73. const response = error.response
  74. const config = error.config
  75. const { COUNT: RETRY_COUNT, DELAY: RETRY_DELAY } = CONSTS.RETRY
  76. if (config && RETRY_COUNT) {
  77. // 设置一个静态属性追踪重试次数
  78. config.__retryCount = config.__retryCount || 0
  79. // 重试次数已用完
  80. if (config.__retryCount >= RETRY_COUNT) {
  81. return Promise.reject(response)
  82. }
  83. config.__retryCount++
  84. // 利用promise处理请求间隔
  85. const backoff = new Promise(resolve => {
  86. setTimeout(() => {
  87. resolve()
  88. }, RETRY_DELAY | 1)
  89. })
  90. // 重新发起请求
  91. return backoff.then(() => service(config))
  92. }
  93. return Promise.reject(response)
  94. }
  95. )
  96. export default {
  97. get(url: string, params?: any) {
  98. return service.get(url, { params })
  99. },
  100. post(url: string, data?: any) {
  101. return service.post(url, data )
  102. },
  103. del(url: string, data?: any) {
  104. return service.delete(url, data)
  105. }
  106. }