Request

coderljw 2024-10-13 Utils
  • Utils
  • Request
大约 1 分钟

# 1. Request

import { message, notification } from 'antd'
import axios from 'axios'
import type { Axios, AxiosPromise, AxiosRequestConfig } from 'axios'
import history from 'history/browser'
import qs from 'qs'
import { stringify } from 'querystring'
import { UserStoreEnum } from '@/constant/store'
import store from '@/utils/store'

enum CodeTypeEnum {
  SUCCESS = 'SUCCESS',
  REDIRECT = 'REDIRECT',
  BACK_PREVIOUS = 'BACK_PREVIOUS',
  ERROR_MESSAGE = 'ERROR_MESSAGE',
  ERROR_NOTIFICATION = 'ERROR_NOTIFICATION',
}

const CodeType = {
  1: CodeTypeEnum.SUCCESS,
  2: CodeTypeEnum.REDIRECT,
  3: CodeTypeEnum.REDIRECT,
  7: CodeTypeEnum.REDIRECT,
  8: CodeTypeEnum.REDIRECT,
  101: CodeTypeEnum.ERROR_MESSAGE,
  403: CodeTypeEnum.ERROR_MESSAGE,
}

const codeMessage = {
  400: '请求错误',
  401: '授权验证失败,请重新登录!',
  403: '无访问权限',
  404: '请求地址错误',
  500: '服务器错误',
  502: '网关错误',
  503: '服务不可用',
  504: '网关超时',
}

const logout = () => {
  store.removeItem(UserStoreEnum.ACCESS_TOKEN)
  setTimeout(() => {
    const loginPath = '/login'
    const { pathname } = history.location
    if (pathname !== loginPath) {
      history.replace({
        pathname: loginPath,
        search: stringify({
          redirect: pathname,
        }),
      })
    }
  }, 1500)
}

interface AxiosExtensionConfig extends AxiosRequestConfig {
  /**
   * @name 跳过错误处理
   */
  skipErrorHandler?: boolean
}

interface AxiosInstance extends Axios {
  (config: AxiosExtensionConfig): AxiosPromise
  (url: string, config?: AxiosExtensionConfig): AxiosPromise
}

const request = axios.create({
  baseURL: APP_BASE_URL,
  // withCredentials: true,
  // xsrfCookieName: 'cToken',
  // xsrfHeaderName: 'cToken',
  paramsSerializer: params => qs.stringify(params, { arrayFormat: 'repeat' }),
}) as AxiosInstance

type ErrorThrowerProps = {
  success: boolean
  code: number
  errorMessage: string
}

// 错误处理
const errorHandler = (error: any, config?: AxiosExtensionConfig) => {
  if (config?.skipErrorHandler) return error
  if (error.name === 'BizError') {
    const { code, errorCode, errorMessage } =
      error.info as ErrorThrowerProps & {
        errorCode: CodeTypeEnum
        errorMessage: string
      }

    const errorStrategy = {
      [CodeTypeEnum.REDIRECT]: () => {
        notification.warning({ message: code, description: errorMessage })
        logout()
      },
      [CodeTypeEnum.BACK_PREVIOUS]: () => {
        notification.warning({ message: code, description: errorMessage })
        history.go(-1)
      },
      [CodeTypeEnum.ERROR_NOTIFICATION]: () => {
        notification.error({ message: code, description: errorMessage })
      },
    }

    const strategy = errorStrategy[errorCode!]
    strategy
      ? strategy()
      : message.error(errorMessage || 'No error message! Please retry.')
  } else if (error.response) {
    const { status } = error.response
    if (codeMessage[status]) {
      if (status === 401) logout()
      notification.error({
        message: status,
        description: codeMessage[status],
      })
    } else message.error('Response error! Please retry.')
  } else if (error.request) {
    message.error('None response! Please retry.')
  } else {
    message.error('Request error! Please retry.')
  }

  return Promise.reject(error)
}

// 请求拦截器
request.interceptors.request.use(async (config: AxiosRequestConfig) => {
  const token = await store.getItem<string>(UserStoreEnum.ACCESS_TOKEN)
  if (token && config.headers) config.headers.token = token

  return config
}, errorHandler)

// 响应拦截器
request.interceptors.response.use(async ({ data, config }: any) => {
  if (data instanceof Blob) return data

  const { success, code, errorMessage } = data
  if (!success) {
    const error = {
      name: 'BizError',
      info: { ...data, errorCode: CodeType[code], errorMessage },
    }
    errorHandler(error, config)
    return Promise.reject(error)
  }

  return data
}, errorHandler)

export default request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
以父之名
周杰伦.mp3