setup.ts 6.9 KB

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