Appearance
Promise 封装 ajax
有哪些注意事项
- 调用的函数如果有可能抛出异常,就需要使用try...catch
- 网络请求失败怎么办?请求失败重新发送,若超过3次,则提示用户请求失败
- 如何封装超时重发函数?
- 输入 get、post有可能输错,使用选择的方式
- onerror错误处理、onload错误处理
- 输出error的时候一定要写错误信息
- get / post 请求返回的数据类型定义一定根据后端接口制定(使用Ts中的泛型)
函数封装
GET 请求封装
type Params = {
name:string;
age:number;
}
// 处理get请求附有参数的情况
// 为了防止XSS攻击,参数必须使用 encodeURIComponent()函数进行编码
export function addUrlParam(url:string, params:Params):string {
url += (url.indexOf('?') === -1 ? '?' : "&");
let key:keyof Params;
for (key in params) {
if (Object.prototype.hasOwnProperty.call(params, key)) {
url += (encodeURIComponent(key) + '=' + encodeURIComponent(params[key]) + '&')
}
}
url = url.replace(/&$/g, ''); // 去除拼接后url中的末尾&
return url;
}
export function get(url:string, params: Params = {name:'lvyuanxin', age: 20}):Promise<[]> {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
url = addUrlParam(url, params);
// 当请求完成的时候会出发onload事件
xhr.onload = () => {
if (xhr.status === 200) {
try {
resolve(JSON.parse(xhr.responseText) );
} catch (error) {
reject('get xhr.res json parse fail')
}
} else {
reject('get xhr load fail ' + xhr.status)
}
}
xhr.onerror = err => {
console.log(err)
}
xhr.ontimeout = err => {
console.log('get 请求超时 ' + err)
}
xhr.timeout = 3000;
xhr.open('get', url);
// 发送请求
xhr.send();
})
}
// 超时重发函数
// version 1
export async function reTryGet(url:string, reTryTimes:number = 3) {
try {
let result = await get(url);
return result;
} catch (err) {
if (reTryTimes - 1 > 0) {
reTryGet(url, reTryTimes - 1);
}
}
}
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
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
对于超时重发网络请求函数的封装,还有其他不同方案:
// version 2
let retryPromise = function(options,times) {
fetch({...options}).then(resolve)
.catch(err=> {
if(times - 1 > 0) {
retryPromise(options,times -1)
}
return reject(err)
})
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
// version 3
async function retryFunction(times, options) {
for (let i = 0; i < times; i++) {
try {
let result = await fetch(options)
return result
} catch (err) {
return new Error(err)
}
}
return new Error('代码除了问题')
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
POST 请求封装
export function post(url:string, data:any):Promise<Object> {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.timeout = 3000;
xhr.open('post', url);
// 当请求完成的时候会出发onload事件
xhr.onload = () => {
if (xhr.status === 200) {
try {
resolve(JSON.parse(xhr.responseText) );
} catch (error) {
reject('post xhr.res json parse fail')
}
} else {
reject('post xhr load fail ' + xhr.status)
}
}
xhr.onerror = err => {
console.log(err)
}
xhr.ontimeout = err => {
console.log('post请求超时 ' + err)
}
xhr.setRequestHeader('content-type', 'application/json') // 客户端告诉服务器返回的数据类型为json
// 发送请求
xhr.send(data);
})
}
export async function reTryPost(url:string, data:any, retryTimes:number = 3) {
try {
let result = await post(url, data);
return result;
} catch (error) {
if (retryTimes - 1 > 0)
reTryPost(url, data, retryTimes - 1)
}
}
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
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