-
Notifications
You must be signed in to change notification settings - Fork 0
/
request.tsx
135 lines (127 loc) · 4.5 KB
/
request.tsx
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
/** @format */
import {stringify} from 'qs'
type HttpMethod = 'get' | 'post' | 'delete' | 'put' | 'patch' | 'head' | 'options'
interface IResponseHook {
(resp: Response): Response
}
interface IRequestOptions {
method?: HttpMethod
headers?: HeadersInit
params?: URLSearchParams | Record<string, string | number | boolean> | string | []
data?: FormData | string | Record<string, any> | Array<any> | BodyInit
timeout?: number
credentials?: RequestCredentials
mod?: RequestMode
prefix?: string
suffix?: string
requestType?: 'json' | 'form'
responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'
hooks?: Array<IResponseHook>
}
const checkStatusHook: IResponseHook = (response: Response): Response => {
if (response.status >= 200 && response.status < 300) {
return response
} else {
const error = new Error(`request error: ${response.statusText}`)
throw error
}
}
const initOptions: IRequestOptions = {
method: 'get',
params: {},
data: '',
timeout: 1000,
credentials: 'same-origin',
headers: {},
mod: 'same-origin',
prefix: '',
suffix: '',
requestType: 'json',
responseType: 'json',
hooks: [checkStatusHook],
}
const buildRequestInit = (options: IRequestOptions): RequestInit => {
const myInit: RequestInit = {}
const opts = {...initOptions, ...options}
const {requestType = 'json', data} = opts
let body: BodyInit | undefined
if (data) {
const dataType = Object.prototype.toString.call(data)
if (dataType === '[object Object]' || dataType === '[object Array]') {
if (requestType === 'json') {
opts.headers = {
Accept: 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
...opts.headers,
}
body = JSON.stringify(data)
} else if (requestType === 'form') {
opts.headers = {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
...opts.headers,
}
body = stringify(data, {arrayFormat: 'repeat', strictNullHandling: true})
}
} else {
// 其他 requestType 自定义header
opts.headers = {
Accept: 'application/json',
...opts.headers,
}
body = data as BodyInit
}
}
myInit.method = opts.method?.toUpperCase()
myInit.headers = opts.headers
myInit.body = body
myInit.credentials = opts.credentials
myInit.mode = opts.mod
return myInit
}
class RequestInstance {
private opts: IRequestOptions
constructor(opts: IRequestOptions) {
this.opts = opts || {}
}
private async _request(method: HttpMethod, url: string, options?: IRequestOptions): Promise<Response> {
const opts = {...this.opts, ...options, method}
const prefix = opts.prefix ?? ''
const suffix = opts.suffix ?? ''
url = `${prefix}${url}${suffix}`
if (opts.params) {
const paramsType = Object.prototype.toString.call(opts.params)
if (paramsType === '[object URLSearchParams]') {
opts.params = opts.params.toString()
} else if (paramsType === '[object Object]' || paramsType === '[object Array]') {
opts.params = stringify(opts.params, {arrayFormat: 'brackets'})
}
const urlSign = url.indexOf('?') !== -1 ? '&' : '?'
url = `${url}${urlSign}${opts.params}`
}
const myRequest = new Request(url)
let resp = fetch(myRequest, buildRequestInit(opts))
opts.hooks = opts.hooks ?? []
for (let hook of opts.hooks) {
resp = resp.then(hook)
}
return resp
}
async get(url: string, options?: IRequestOptions) {
return this._request('get', url, options)
}
async post(url: string, options?: IRequestOptions) {
return this._request('post', url, options)
}
async delete(url: string, options?: IRequestOptions) {
return this._request('delete', url, options)
}
async put(url: string, options?: IRequestOptions) {
return this._request('put', url, options)
}
}
const request = (opts: IRequestOptions = initOptions) => {
return new RequestInstance(opts)
}
export const extend = (initOpts: IRequestOptions) => request(initOpts)
export default request({})