# Loading
集中处理项目中的loading 问题。
# 核心思想
劫持request,每次调接口都会往 loadingQueue 中 push 一个当前 loading的id,每次接口调用结束,删除对应的id,如果 loadingQueue 有值 就保持loading 展示,如果 loadingQueue 为空数组,卸载loading组件。
import ReactDOM from 'react-dom';
import PageLoading from '@/components/PageLoading';
const TIMEOUT_TIME = 1000 * 60; // 超时时间 60s
const loadingMount = () => {
ReactDOM.render(
<PageLoading />,
document.querySelector('.fullScreenLoading'),
);
};
const loadingUnmount = () => {
ReactDOM.unmountComponentAtNode(document.querySelector('.fullScreenLoading') as Element);
};
const handleFullScreenLoading = () => {
let loadingQueue: any[] = [];
let timePlan: any = null;
const timeOutStart = () =>
setTimeout(() => {
// eslint-disable-next-line no-use-before-define
clearAll();
clearTimeout(timePlan);
}, TIMEOUT_TIME);
const setLoadingRootEle = () => {
const attr = document.createAttribute('class');
attr.value = 'fullScreenLoading';
const node = document.createElement('div');
node.setAttributeNode(attr);
setTimeout(() => {
// that umi render content component maybe replace all root children element, so append child async
document?.querySelector('#root')?.appendChild(node);
}, 0);
};
const renderLoading = () => {
if (loadingQueue.length === 1) {
timePlan = timeOutStart();
loadingMount();// 单例模式
} else if (!loadingQueue.length) {
clearTimeout(timePlan);
loadingUnmount();
}
};
const showLoading = (loadingId: number | string) => {
loadingQueue.push({ id: loadingId });
renderLoading();
};
const closeLoading = (loadingId: number | string) => {
if (loadingQueue.length) {
loadingQueue = loadingQueue.filter((item) => item.id !== loadingId);
}
renderLoading();
};
const clearAll = () => {
loadingQueue = [];
renderLoading();
};
setLoadingRootEle();
return (loadingId: number | string) => {
if (loadingId) {
showLoading(loadingId);
}
return {
renderLoading,
showLoading,
closeLoading,
clearAll,
};
};
};
export default handleFullScreenLoading();
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
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
# 应用
import { request } from 'umi';
import handleLoading from '../utils/handleFullScreenLoading';
import handleWithLoginTimeout from '../utils/handleWithLoginTimeout';
type Method = 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
const resetInterval = handleWithLoginTimeout();
const calcParams = (param: { method: Method; [key: string]: any }) => {
const { method } = param || {};
const key = (method === 'GET' && 'params') || 'data';
const { withoutLoading, resetTokenTime = true, ...restParams } = param[key] || {};
const loadingId = (!withoutLoading && `request_loading_${Date.now().toString(36)}`) || '';
return {
params: {
...param,
[key]: restParams,
},
loadingId,
resetTokenTime,
};
};
const requestWithLoading = <Res>(url: string, originParam: { method: Method; [key: string]: any }) => {
const { params, loadingId, resetTokenTime } = calcParams(originParam);
// loading start;
const { closeLoading } = handleLoading(loadingId);
return (
request<{
success: boolean;
code: string;
ext: string;
msg: string;
result: Res;
}>(url, params)
.then((res) => {
resetInterval(resetTokenTime);
return Promise.resolve(res);
})
// eslint-disable-next-line arrow-body-style
.catch((error) => {
return Promise.resolve({ success: false, code: '', msg: error, result: null });
})
.finally(() => {
// loading end;
closeLoading(loadingId);
})
);
};
export default requestWithLoading;
export function Request<T, Res>(url: string, method: Method = 'GET') {
return (params?: T, options?: Record<string, unknown>) => {
const key = (method === 'GET' && 'params') || 'data';
return requestWithLoading<Res>(url, {
method,
[key]: params,
...options,
});
};
}
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
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
← 添加千分符 loginTimeout →