perf: cancel the request when leaving page

This commit is contained in:
jialin
2026-01-16 16:53:38 +08:00
parent 3e359a69c7
commit b4f69a4e2e
6 changed files with 60 additions and 44 deletions
+18 -9
View File
@@ -58,11 +58,12 @@ export default function useTableFetch<T>(
updateManually updateManually
} = options; } = options;
const pollingRef = useRef<any>(null); const pollingRef = useRef<any>(null);
const chunkRequedtRef = useRef<any>(null); const chunkRequestRef = useRef<any>(null);
const modalRef = useRef<any>(null); const modalRef = useRef<any>(null);
const rowSelection = useTableRowSelection(); const rowSelection = useTableRowSelection();
const { sortOrder, handleMultiSortChange } = useTableMultiSort(); const { sortOrder, handleMultiSortChange } = useTableMultiSort();
const axiosTokenRef = useRef<any>(null); const axiosTokenRef = useRef<any>(null);
const timerIDRef = useRef<any>(null);
// ======= to resolve worker upate issue ======= // ======= to resolve worker upate issue =======
const shouldUpdateRef = useRef(false); const shouldUpdateRef = useRef(false);
@@ -238,16 +239,16 @@ export default function useTableFetch<T>(
// ============================================ // ============================================
}; };
const createModelsChunkRequest = async (params?: any) => { const createTableListChunkRequest = async (params?: any) => {
if (!API || !watch) return; if (!API || !watch) return;
shouldUpdateRef.current = false; shouldUpdateRef.current = false;
chunkRequedtRef.current?.current?.cancel?.(); chunkRequestRef.current?.current?.cancel?.();
try { try {
const currentParams = params || queryParams; const currentParams = params || queryParams;
const query = _.omit(currentParams, ['page', 'perPage']); const query = _.omit(currentParams, ['page', 'perPage']);
chunkRequedtRef.current = setChunkRequest({ chunkRequestRef.current = setChunkRequest({
url: `${API}?${qs.stringify(_.pickBy(query, (val: any) => !!val))}`, url: `${API}?${qs.stringify(_.pickBy(query, (val: any) => !!val))}`,
handler: updateHandler handler: updateHandler
}); });
@@ -286,7 +287,7 @@ export default function useTableFetch<T>(
setQueryParams(newQueryParams); setQueryParams(newQueryParams);
await fetchData({ query: newQueryParams }); await fetchData({ query: newQueryParams });
if (watch && !options?.paginate) { if (watch && !options?.paginate) {
createModelsChunkRequest(newQueryParams); createTableListChunkRequest(newQueryParams);
} }
}; };
@@ -338,7 +339,6 @@ export default function useTableFetch<T>(
name: row.name, name: row.name,
...options, ...options,
async onOk() { async onOk() {
console.log('OK');
await deleteAPI?.(row.id, { await deleteAPI?.(row.id, {
...modalRef.current?.configuration ...modalRef.current?.configuration
}); });
@@ -398,15 +398,24 @@ export default function useTableFetch<T>(
}, [dataSource.loadend, queryParams]); }, [dataSource.loadend, queryParams]);
useEffect(() => { useEffect(() => {
let mounted = true;
const init = async () => { const init = async () => {
await fetchData(); await fetchData();
setTimeout(() => {
createModelsChunkRequest(); timerIDRef.current = setTimeout(() => {
if (mounted) {
createTableListChunkRequest();
}
}, 200); }, 200);
}; };
init(); init();
return () => { return () => {
chunkRequedtRef.current?.cancel?.(); mounted = false;
clearTimeout(timerIDRef.current);
chunkRequestRef.current?.current?.cancel?.();
axiosTokenRef.current?.cancel?.(); axiosTokenRef.current?.cancel?.();
cacheDataListRef.current = []; cacheDataListRef.current = [];
}; };
+8 -2
View File
@@ -156,9 +156,15 @@ export async function queryClusterItem(params: { id: number }, options?: any) {
}); });
} }
export async function queryClusterToken(params: { id: number }) { export async function queryClusterToken(
params: { id: number },
options?: {
token?: any;
}
) {
return request(`${CLUSTERS_API}/${params.id}/${CLUSTER_TOKEN}`, { return request(`${CLUSTERS_API}/${params.id}/${CLUSTER_TOKEN}`, {
method: 'GET' method: 'GET',
cancelToken: options?.token
}); });
} }
@@ -1,4 +1,5 @@
import GSDrawer from '@/components/scroller-modal/gs-drawer'; import GSDrawer from '@/components/scroller-modal/gs-drawer';
import { createAxiosToken } from '@/hooks/use-chunk-request';
import ColumnWrapper from '@/pages/_components/column-wrapper'; import ColumnWrapper from '@/pages/_components/column-wrapper';
import useAddWorkerMessage from '@/pages/cluster-management/hooks/use-add-worker-message'; import useAddWorkerMessage from '@/pages/cluster-management/hooks/use-add-worker-message';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
@@ -59,8 +60,10 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
stepList = [] stepList = []
} = props || {}; } = props || {};
const intl = useIntl(); const intl = useIntl();
const { addedCount, createModelsChunkRequest } = useAddWorkerMessage(); const { addedCount, createModelsChunkRequest, chunkRequestRef } =
useAddWorkerMessage();
const firstLoad = React.useRef(true); const firstLoad = React.useRef(true);
const axiosTokenRef = React.useRef<any>(null);
const [registrationInfo, setRegistrationInfo] = React.useState<{ const [registrationInfo, setRegistrationInfo] = React.useState<{
token: string; token: string;
image: string; image: string;
@@ -75,7 +78,12 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
const handleOnClusterChange = async (value: number, row?: any) => { const handleOnClusterChange = async (value: number, row?: any) => {
try { try {
const data = await queryClusterToken({ id: value }); axiosTokenRef.current?.cancel?.();
axiosTokenRef.current = createAxiosToken();
const data = await queryClusterToken(
{ id: value },
{ token: axiosTokenRef.current.token }
);
firstLoad.current = false; firstLoad.current = false;
setRegistrationInfo({ setRegistrationInfo({
...data, ...data,
@@ -92,12 +100,17 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
} }
return () => { return () => {
firstLoad.current = true; firstLoad.current = true;
chunkRequestRef.current?.current?.cancel?.();
axiosTokenRef.current?.cancel?.();
}; };
}, [open, cluster_id]); }, [open, cluster_id]);
useEffect(() => { useEffect(() => {
if (open) { if (open) {
createModelsChunkRequest(); createModelsChunkRequest();
} else {
chunkRequestRef.current?.current?.cancel?.();
axiosTokenRef.current?.cancel?.();
} }
}, [open]); }, [open]);
@@ -1,7 +1,7 @@
import BaseSelect from '@/components/seal-form/base/select'; import BaseSelect from '@/components/seal-form/base/select';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Spin, Typography } from 'antd'; import { Spin, Typography } from 'antd';
import { useEffect } from 'react'; import { useEffect, useState } from 'react';
import { useAddWorkerContext } from './add-worker-context'; import { useAddWorkerContext } from './add-worker-context';
import { AddWorkerStepProps, StepNamesMap } from './config'; import { AddWorkerStepProps, StepNamesMap } from './config';
import { Title } from './constainers'; import { Title } from './constainers';
@@ -20,10 +20,17 @@ const SelectCluster: React.FC<AddWorkerStepProps> = ({ disabled }) => {
} = useAddWorkerContext(); } = useAddWorkerContext();
const intl = useIntl(); const intl = useIntl();
const clusterId = summary.get('cluster_id'); const [clusterId, setClusterId] = useState<number | null>(
summary.get('cluster_id')
);
const stepIndex = stepList.indexOf(StepNamesMap.SelectCluster) + 1; const stepIndex = stepList.indexOf(StepNamesMap.SelectCluster) + 1;
const handleOnClusterChange = (value: number, option: any) => {
setClusterId(value);
onClusterChange?.(value, option);
};
useEffect(() => { useEffect(() => {
const unregister = registerField('cluster_id'); const unregister = registerField('cluster_id');
return () => { return () => {
@@ -34,6 +41,7 @@ const SelectCluster: React.FC<AddWorkerStepProps> = ({ disabled }) => {
useEffect(() => { useEffect(() => {
updateField('cluster_id', registrationInfo.cluster_id); updateField('cluster_id', registrationInfo.cluster_id);
// update cluster name in summary // update cluster name in summary
setClusterId(registrationInfo.cluster_id);
const selectedCluster = clusterList?.find( const selectedCluster = clusterList?.find(
(item) => item.value === registrationInfo.cluster_id (item) => item.value === registrationInfo.cluster_id
); );
@@ -76,7 +84,7 @@ const SelectCluster: React.FC<AddWorkerStepProps> = ({ disabled }) => {
defaultValue={registrationInfo.cluster_id} defaultValue={registrationInfo.cluster_id}
options={clusterList} options={clusterList}
value={clusterId} value={clusterId}
onChange={onClusterChange} onChange={handleOnClusterChange}
style={{ width: '100%' }} style={{ width: '100%' }}
/> />
{!clusterLoading && !clusterList?.length && ( {!clusterLoading && !clusterList?.length && (
@@ -64,6 +64,7 @@ export default function useAddWorkerMessage() {
return { return {
addedCount, addedCount,
chunkRequestRef,
createModelsChunkRequest createModelsChunkRequest
}; };
} }
+7 -28
View File
@@ -240,6 +240,7 @@ export const useCheckCompatibility = () => {
message: '' message: ''
}; };
} }
const { const {
compatible, compatible,
compatibility_messages = [], compatibility_messages = [],
@@ -263,13 +264,10 @@ export const useCheckCompatibility = () => {
Object.entries(resource_claim_by_cluster_id || {}) Object.entries(resource_claim_by_cluster_id || {})
); );
// current cluster resource claim // current cluster resource claim: {ram: number, vram: number}
const resource_claim = resourceClaimMap.get(`${cluster_id}`); const resource_claim = resourceClaimMap.get(`${cluster_id}`);
const hasClaim = !!resource_claim?.ram || !!resource_claim?.vram; const hasClaim = resourceClaimMap.has(`${cluster_id}`);
// current cluster is not available, but other clusters are available
const othersAvailable = !hasClaim && resourceClaimMap.size > 0;
let compatibilityMessage = compatibility_messages.join(' '); let compatibilityMessage = compatibility_messages.join(' ');
@@ -288,8 +286,8 @@ export const useCheckCompatibility = () => {
}; };
if (hasClaim) { if (hasClaim) {
const ram = convertFileSize(resource_claim.ram, 2); const ram = convertFileSize(resource_claim?.ram || 0, 2);
const vram = convertFileSize(resource_claim.vram, 2); const vram = convertFileSize(resource_claim?.vram || 0, 2);
let messageId = 'models.form.check.claims'; let messageId = 'models.form.check.claims';
if (!ram) { if (!ram) {
messageId = 'models.form.check.claims2'; messageId = 'models.form.check.claims2';
@@ -301,30 +299,11 @@ export const useCheckCompatibility = () => {
title: intl.formatMessage({ id: 'models.form.check.passed' }), title: intl.formatMessage({ id: 'models.form.check.passed' }),
message: intl.formatMessage({ id: messageId }, { ram, vram }) message: intl.formatMessage({ id: messageId }, { ram, vram })
}; };
} else if (
othersAvailable &&
!scheduling_messages?.length &&
!compatibility_messages?.length
) {
// no specific messages, but other clusters are available
msgData = {
title: intl.formatMessage({
id: 'models.form.check.clusterUnavailable'
}),
message: intl.formatMessage(
{
id: 'models.form.check.otherClustersAvailable'
},
{
clusters: getAvailableClusters(Array.from(resourceClaimMap.keys()))
}
)
};
} }
return { return {
show: !compatible || hasClaim || othersAvailable, show: !compatible || hasClaim,
type: !compatible || othersAvailable ? 'warning' : 'success', type: !compatible ? 'warning' : 'success',
...msgData ...msgData
}; };
}; };