返回 AiToEarn
FetchService.ts
根目录 / project / aitoearn-web / src / utils / request / FetchService.ts
1 import type { IFetchServiceConfig, RequestParams } from './types'
2
3 /**
4 * 泛型:
5 * T=返回类型
6 */
7 class FetchService<T = Response> {
8 baseURL: string
9 // 请求拦截
10 requestInterceptor?: (requestParams: RequestParams) => RequestParams | void | null
11
12 // 响应拦截
13 responseInterceptor?: (response: Response) => T
14
15 constructor({ baseURL, requestInterceptor, responseInterceptor }: IFetchServiceConfig<T>) {
16 this.baseURL = baseURL
17 this.requestInterceptor = requestInterceptor
18 this.responseInterceptor = responseInterceptor
19 }
20
21 // 过滤一个字典 value 为undefined的key
22 private _filterDictUndefined(data: object) {
23 return Object.fromEntries(Object.entries(data).filter(([_, value]) => value !== undefined))
24 }
25
26 private _stringifySearchParams(data: object) {
27 const searchParams = new URLSearchParams()
28 Object.entries(data).forEach(([key, value]) => {
29 if (value !== undefined && value !== null) {
30 searchParams.set(key, String(value))
31 }
32 })
33 return searchParams.toString()
34 }
35
36 public async request(requestParams: RequestParams): Promise<T> {
37 return new Promise(async (resolve, reject) => {
38 // 请求拦截
39 if (this.requestInterceptor) {
40 const newRequestParams = this.requestInterceptor(requestParams)
41 if (!newRequestParams)
42 return reject(null)
43 requestParams = newRequestParams
44 }
45
46 let baseURL = this.baseURL
47 if (requestParams.url.startsWith('assets/') && requestParams.url.endsWith('/uploadSign') && process.env.NEXT_PUBLIC_OSS_TEMP_URL) {
48 baseURL = process.env.NEXT_PUBLIC_OSS_TEMP_URL
49 }
50
51 // body 参数处理
52 const fetchURL = requestParams.url.startsWith('http')
53 ? requestParams.url
54 : baseURL + requestParams.url
55 if (!requestParams.body && requestParams.data) {
56 // 检查是否为FormData
57 if (requestParams.data instanceof FormData) {
58 // 如果是FormData,直接设置为body,不需要转JSON
59 requestParams = {
60 ...requestParams,
61 body: requestParams.data,
62 // 不手动设置Content-Type,让浏览器自动处理
63 }
64 }
65 else {
66 // 非FormData对象走原来的逻辑
67 requestParams.data = this._filterDictUndefined(requestParams.data)
68 requestParams = {
69 ...requestParams,
70 body: requestParams.body ? requestParams.body : JSON.stringify(requestParams.data),
71 headers: {
72 ...(requestParams.headers || {}),
73 'content-type': new Headers(requestParams.headers).get('Content-Type') ?? 'application/json',
74 },
75 }
76 }
77 }
78
79 // params 参数处理
80 let params: string | null = null
81 if (requestParams.params) {
82 params = this._stringifySearchParams(requestParams.params)
83 }
84
85 const res = await fetch(params ? `${fetchURL}?${params}` : fetchURL, {
86 ...requestParams,
87 })
88
89 if (this.responseInterceptor) {
90 return resolve(this.responseInterceptor(res))
91 }
92
93 resolve(res as T)
94 })
95 }
96 }
97
98 export default FetchService
99
99 lines TYPESCRIPT