request.ts 3.7 KB

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