request.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. if (request?.method !== 'get') {
  45. request.headers['X-CSRF-Token'] = storage.get('csrf_token')
  46. }
  47. request.headers['bidsectionId'] = tenderStore.bid
  48. return Promise.resolve(request)
  49. },
  50. err => {
  51. return Promise.reject(err)
  52. }
  53. )
  54. /**
  55. * response 拦截器
  56. */
  57. service.interceptors.response.use(
  58. (response: AxiosResponse) => {
  59. removePending(response.config)
  60. const data: ResponseData = response.data
  61. // 对Code不等于Success进行message提示
  62. if (data && data.code !== consts.RET_CODE.SUCCESS) {
  63. message.error(data.msg)
  64. if (consts.TOKEN_INVALID_CODE.includes(data.code)) {
  65. userStore.logout()
  66. }
  67. if (data.code === consts.RET_CODE.UN_PERMISSION) {
  68. // 防止无权访问
  69. history.goBack()
  70. }
  71. }
  72. if (response.config.method?.toLocaleUpperCase() === 'GET') {
  73. const token = response?.headers['x-csrf-token']
  74. storage.set('csrf_token', token)
  75. }
  76. return Promise.resolve(response)
  77. },
  78. error => {
  79. const response = error.response
  80. const config = error.config
  81. const { COUNT: RETRY_COUNT, DELAY: RETRY_DELAY } = consts.RETRY
  82. if (config && RETRY_COUNT) {
  83. // 设置一个静态属性追踪重试次数
  84. config.__retryCount = config.__retryCount || 0
  85. // 重试次数已用完
  86. if (config.__retryCount >= RETRY_COUNT) {
  87. return Promise.reject(response)
  88. }
  89. config.__retryCount++
  90. // 利用promise处理请求间隔
  91. const backoff = new Promise(resolve => {
  92. setTimeout(() => {
  93. resolve('')
  94. }, RETRY_DELAY | 1)
  95. })
  96. // 重新发起请求
  97. return backoff.then(() => service(config))
  98. }
  99. return Promise.reject(response)
  100. }
  101. )
  102. export default {
  103. get(url: string, params?: any) {
  104. return service.get(url, { params })
  105. },
  106. post(url: string, data?: any) {
  107. return service.post(url, data)
  108. },
  109. del(url: string, data?: any) {
  110. return service.delete(url, { params: data })
  111. },
  112. uploadFile(url: string, formData: FormData, config?: AxiosRequestConfig) {
  113. return service.post(url, formData, config)
  114. }
  115. }