/** * 网络请求配置 */ import { tenderStore, userStore } from '@/store/mobx' import { PendingType, ResponseData } from '@/types/request' import consts from '@/utils/consts' import { storage } from '@/utils/util' import { message } from 'antd' import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' import history from '../history' const pending: Array = [] const removePending = (config: AxiosRequestConfig) => { for (const key in pending) { const item: number = +key const list: PendingType = pending[key] // 当前请求在数组中存在时执行函数体 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) ) { // 执行取消操作 list.cancel('操作太频繁,请稍后再试') // 从数组中移除记录 pending.splice(item, 1) } } } const service = axios.create({ baseURL: process.env.NODE_ENV === 'development' ? consts.BASE_URL.DEV : consts.BASE_URL.PROD, timeout: 5000, withCredentials: true }) /** * request 拦截器 */ service.interceptors.request.use( request => { removePending(request) request.cancelToken = new axios.CancelToken(func => { pending.push({ url: request.url, method: request.method, params: request.params, data: request.data, cancel: func }) }) let csrf_token try { csrf_token = storage.get('csrf_token') } catch (error) { throw new Error('csrf_token不存在') } if (request?.method !== 'get' && csrf_token) { request.headers['X-CSRF-Token'] = csrf_token } const bidsectionId = tenderStore.bid if (bidsectionId) { request.headers['bidsectionId'] = tenderStore.bid } return Promise.resolve(request) }, err => { return Promise.reject(err) } ) /** * response 拦截器 */ service.interceptors.response.use( (response: AxiosResponse) => { removePending(response.config) const data: ResponseData = response.data // 对Code不等于Success进行message提示 if (data && data.code === consts.RET_CODE.FAIL) { message.error(data.msg) } if (consts.TOKEN_INVALID_CODE.includes(data.code)) { userStore.logout() } if (data.code === consts.RET_CODE.UN_PERMISSION) { // 防止无权访问 history.goBack() } if (response.config.method?.toLocaleUpperCase() === 'GET') { const token = response?.headers['x-csrf-token'] storage.set('csrf_token', token) } return Promise.resolve(response) }, error => { const response = error.response const config = error.config const { COUNT: RETRY_COUNT, DELAY: RETRY_DELAY } = consts.RETRY if (config && RETRY_COUNT) { // 设置一个静态属性追踪重试次数 config.__retryCount = config.__retryCount || 0 // 重试次数已用完 if (config.__retryCount >= RETRY_COUNT) { return Promise.reject(response) } config.__retryCount++ // 利用promise处理请求间隔 const backoff = new Promise(resolve => { setTimeout(() => { resolve('') }, RETRY_DELAY | 1) }) // 重新发起请求 return backoff.then(() => service(config)) } return Promise.reject(response) } ) export default { get(url: string, params?: any) { return service.get(url, { params }) }, post(url: string, data?: any) { return service.post(url, data) }, del(url: string, data?: any) { return service.delete(url, { params: data }) }, uploadFile(url: string, formData: FormData, config?: AxiosRequestConfig) { return service.post(url, formData, config) } }