setup.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. import Axios from 'axios'
  2. import { ResCode } from './constant'
  3. import { setOfflineAxios } from './offline'
  4. import type { AxiosResponse, AxiosRequestConfig } from 'axios'
  5. export type ResErrorHandler = <D, T extends ResData<D>>(response: AxiosResponse<T>, data?: T) => void
  6. export type ReqErrorHandler = <T>(err: Error, response: AxiosRequestConfig<T>) => void
  7. export type ResData<T> = { code: ResCode, message: string, data: T, msg: string }
  8. export type Hook = {
  9. before?: (config: AxiosRequestConfig) => void
  10. after?: (config: AxiosRequestConfig) => void
  11. }
  12. export const axiosFactory = () => {
  13. const axiosRaw = Axios.create()
  14. const axiosConfig = {
  15. token: localStorage.getItem('token'),
  16. unTokenSet: [] as string[],
  17. unReqErrorSet: [] as string[],
  18. unResErrorSet: [] as string[],
  19. resErrorHandler: [] as ResErrorHandler[],
  20. reqErrorHandler: [] as ReqErrorHandler[],
  21. unLoadingSet: [] as string[],
  22. hook: [] as Hook[]
  23. }
  24. type AxiosConfig = typeof axiosConfig
  25. type ExponseApi<K extends keyof AxiosConfig> =
  26. { set: (val: AxiosConfig[K]) => void }
  27. & (AxiosConfig[K] extends Array<any>
  28. ? {
  29. add: (...val: AxiosConfig[K]) => void,
  30. del: (...val: AxiosConfig[K]) => void
  31. }
  32. : { del: () => void })
  33. const getExponseApi = <K extends keyof AxiosConfig>(key: K): ExponseApi<K> => {
  34. let axiosObj = axiosConfig[key] as any[]
  35. const apis: any = {
  36. set (val: AxiosConfig[K]) {
  37. console.error('set', key, val)
  38. axiosObj = axiosConfig[key] = val as any
  39. }
  40. }
  41. if (Array.isArray(axiosObj)) {
  42. apis.add = (...val: any[]) => {
  43. axiosObj.push(...val)
  44. }
  45. apis.del = (...val: any[]) => {
  46. if (val) {
  47. apis.set(axiosObj.filter((item: any) => !val?.includes(item)) as any)
  48. } else {
  49. axiosObj.length = 0
  50. }
  51. }
  52. } else {
  53. apis.del = () => {
  54. axiosConfig[key] = undefined as any
  55. }
  56. }
  57. return apis
  58. }
  59. const getToken = () => axiosConfig.token
  60. const setToken = (token: string) => {
  61. localStorage.setItem('token', token)
  62. axiosConfig.token = token
  63. }
  64. const delToken = () => {
  65. localStorage.removeItem('token')
  66. axiosConfig.token = null
  67. }
  68. const {
  69. set: setUnsetTokenURLS,
  70. add: addUnsetTokenURLS,
  71. del: delUnsetTokenURLS
  72. } = getExponseApi('unTokenSet')
  73. const {
  74. set: setResErrorHandler,
  75. add: addResErrorHandler,
  76. del: delResErrorHandler
  77. } = getExponseApi('resErrorHandler')
  78. const {
  79. set: setUnsetReqErrorURLS,
  80. add: addUnsetReqErrorURLS,
  81. del: delUnsetReqErrorURLS
  82. } = getExponseApi('unReqErrorSet')
  83. const {
  84. set: setReqErrorHandler,
  85. add: addReqErrorHandler,
  86. del: delReqErrorHandler
  87. } = getExponseApi('reqErrorHandler')
  88. const {
  89. set: setUnsetResErrorURLS,
  90. add: addUnsetResErrorURLS,
  91. del: delUnsetResErrorURLS
  92. } = getExponseApi('unResErrorSet')
  93. const {
  94. set: setHook,
  95. add: addHook,
  96. del: delHook
  97. } = getExponseApi('hook')
  98. const setDefaultURI = (url: string) => {
  99. axiosRaw.defaults.baseURL = url
  100. }
  101. const matchURL = (urls: string[], config: AxiosRequestConfig<any>) =>
  102. config && config.url && urls.includes(config.url)
  103. const callErrorHandler = (key: 'req' | 'res', ...args: any[]) => {
  104. Promise.resolve()
  105. .then(() => {
  106. const api = `${key}ErrorHandler`
  107. ;(axiosConfig as any)[api].forEach((handler: any) => handler(...args))
  108. })
  109. }
  110. axiosRaw.interceptors.request.use(
  111. config => {
  112. for (const hook of axiosConfig.hook) {
  113. hook.before && hook.before(config)
  114. }
  115. // console.log(axiosConfig.unTokenSet)
  116. if (!matchURL(axiosConfig.unTokenSet, config)) {
  117. if (!axiosConfig.token) {
  118. if (!offline && !matchURL(axiosConfig.unReqErrorSet, config)) {
  119. console.log(config)
  120. const error = new Error('缺少token')
  121. callErrorHandler('req', error, config)
  122. throw error
  123. }
  124. } else {
  125. config.headers = {
  126. ...config.headers,
  127. token: axiosConfig.token
  128. }
  129. }
  130. }
  131. return config
  132. }
  133. )
  134. offline && setOfflineAxios(axiosRaw)
  135. axiosRaw.interceptors.response.use(
  136. (response: AxiosResponse<ResData<any>>) => {
  137. for (const hook of axiosConfig.hook) {
  138. hook.after && hook.after(response.config)
  139. }
  140. if (matchURL(axiosConfig.unResErrorSet, response.config)) {
  141. return response
  142. }
  143. if (response.status !== 200) {
  144. callErrorHandler('res', response)
  145. throw new Error(response.statusText)
  146. } else if (response.data.code !== ResCode.SUCCESS) {
  147. callErrorHandler('res', response, response.data)
  148. if (response.data.code === ResCode.TOKEN_INVALID) {
  149. delToken()
  150. }
  151. throw new Error(response?.data?.message)
  152. } else {
  153. return response.data.data
  154. }
  155. },
  156. (err) => {
  157. for (const hook of axiosConfig.hook) {
  158. hook.after && hook.after(err.config)
  159. }
  160. if (!matchURL(axiosConfig.unResErrorSet, err.config)) {
  161. callErrorHandler('res', err.response)
  162. }
  163. throw new Error(err.response && err.response.statusText)
  164. }
  165. )
  166. type AxiosProcess = {
  167. getUri(config?: AxiosRequestConfig): string;
  168. request<R = any, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
  169. get<R = any, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  170. delete<R = any, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  171. head<R = any, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  172. options<R = any, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
  173. post<R = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  174. put<R = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  175. patch<R = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  176. postForm<R = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  177. putForm<R = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  178. patchForm<R = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
  179. }
  180. interface AxiosInstanceProcess extends AxiosProcess {
  181. <R = any>(config: AxiosRequestConfig): Promise<R>;
  182. <R = any>(url: string, config?: AxiosRequestConfig): Promise<R>;
  183. }
  184. const axios: AxiosInstanceProcess = axiosRaw as any
  185. return {
  186. axios,
  187. getToken,
  188. setToken,
  189. delToken,
  190. setUnsetTokenURLS,
  191. addUnsetTokenURLS,
  192. delUnsetTokenURLS,
  193. setResErrorHandler,
  194. addResErrorHandler,
  195. delResErrorHandler,
  196. setUnsetReqErrorURLS,
  197. addUnsetReqErrorURLS,
  198. delUnsetReqErrorURLS,
  199. setReqErrorHandler,
  200. addReqErrorHandler,
  201. delReqErrorHandler,
  202. setUnsetResErrorURLS,
  203. addUnsetResErrorURLS,
  204. delUnsetResErrorURLS,
  205. setDefaultURI,
  206. setHook,
  207. addHook,
  208. delHook,
  209. }
  210. }
  211. export default axiosFactory