请求loading的优化处理

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
// 希望响应时间小于100ms时不展示 loading 动画,大于100ms时展示300ms的 loading 动画时间 (loading 动画时间 至少持续 300ms)

// 响应时间超过 ms 的情况才展示 loading 动画 的辅助函数
const timeout = (ms) => {
new Promise((_, reject) => {
setTimeout(() => {
reject(Symbol.for('timeout'))
}, ms)
})
}

// loading 动画时间至少持续 ms 时的辅助函数
const delay = (ms) => {
new Promise((resolve, _) => {
setTimeout(() => {
resolve()
}, ms)
})
}

/*
config: axios 的配置
target: true 表示 要使用 loading
timeoutTime: 接口响应事件超过 timeoutTime 才显示 loading
delayTime: loading 时间至少持续 delayTime
*/
const request = ({ config, target, timeoutTime = 100, delayTime = 300 }) => {
// 返回 promise 的 ajax 请求
const promise = axios(config)

const startLoading = target => {
if (!target) return
// startLoading
}

const endLoading = () => {
// endLoading
}

const handleSuccess = data => {
// 兼容 Promise.all 和 Promise.race 的返回值
const response = Array.isArray(data) ? data[0] : data
// 处理成功的情况
return Promise.resolve(response.data)
}

const handleError = ({ response }) => {
return Promise.reject(response)
}

/*
如果 请求promise 先走完,会调用 then 里的 handeleSuccess, 直接将结果 resolve 出去。
如果 timeout 先走完,timeout 里会 reject 错误,调用 catch 里的后续操作,和 race 竞争的这个 promise 则会被终止。
在 catch 里面,显示Loading,然后再调用 promise.all,保证至少 loading 显示 delayTime 时间。
*/
return Promise.race([promise, timeout(timeoutTime)])
.then(handleSuccess)
.catch(err => {
if (Symbol.for('timeout') === err) {
startLoading(target)
return Promise.all([promise, delay(delayTime)])
.then(handleSuccess)
.catch(handleError)
.finally(() => {
endLoading()
})
}
return handleError(err)
})
}

请求loading的优化处理
http://example.com/2023/03/14/请求loading的优化处理/
Author
John Doe
Posted on
March 14, 2023
Licensed under