refactor: 更新 Worker 消息类型以支持生成任务 ID
This commit is contained in:
@@ -8,7 +8,8 @@ import type {
|
||||
FieldConfig,
|
||||
GenerateResult,
|
||||
GenerateProgress,
|
||||
WorkerMessage,
|
||||
WorkerRequestMessage,
|
||||
WorkerResponseMessage,
|
||||
} from '@/types/testDataGenerator';
|
||||
|
||||
export interface UseGeneratorReturn {
|
||||
@@ -35,6 +36,7 @@ export function useGenerator(): UseGeneratorReturn {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const workerRef = useRef<Worker | null>(null);
|
||||
const generationIdRef = useRef(0);
|
||||
|
||||
// 清理 Worker
|
||||
useEffect(() => {
|
||||
@@ -58,22 +60,30 @@ export function useGenerator(): UseGeneratorReturn {
|
||||
type: 'module',
|
||||
});
|
||||
|
||||
worker.onmessage = (e: MessageEvent<WorkerMessage>) => {
|
||||
worker.onmessage = (e: MessageEvent<WorkerResponseMessage>) => {
|
||||
const data = e.data;
|
||||
const { type } = data;
|
||||
|
||||
if (data.generationId !== generationIdRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'progress':
|
||||
setProgress(data.payload as GenerateProgress);
|
||||
setProgress(data.payload);
|
||||
break;
|
||||
case 'complete':
|
||||
setIsGenerating(false);
|
||||
setResult(data.payload as GenerateResult);
|
||||
if (data.payload.success) {
|
||||
setResult(data.payload);
|
||||
} else if (data.payload.error && data.payload.error !== '生成已取消') {
|
||||
setError(data.payload.error);
|
||||
}
|
||||
setProgress(null);
|
||||
break;
|
||||
case 'error':
|
||||
setIsGenerating(false);
|
||||
setError((data.payload as { error: string }).error);
|
||||
setError(data.payload.error);
|
||||
setProgress(null);
|
||||
break;
|
||||
}
|
||||
@@ -100,15 +110,17 @@ export function useGenerator(): UseGeneratorReturn {
|
||||
(fields: FieldConfig[], count: number, csvMode = false) => {
|
||||
if (isGenerating) return;
|
||||
|
||||
const generationId = ++generationIdRef.current;
|
||||
|
||||
setIsGenerating(true);
|
||||
setProgress(null);
|
||||
setResult(null);
|
||||
setError(null);
|
||||
|
||||
const worker = getWorker();
|
||||
const message: WorkerMessage = {
|
||||
const message: WorkerRequestMessage = {
|
||||
type: 'start',
|
||||
payload: { fields, count, csvMode },
|
||||
payload: { generationId, fields, count, csvMode },
|
||||
};
|
||||
worker.postMessage(message);
|
||||
},
|
||||
@@ -120,7 +132,8 @@ export function useGenerator(): UseGeneratorReturn {
|
||||
*/
|
||||
const cancel = useCallback(() => {
|
||||
if (workerRef.current && isGenerating) {
|
||||
const message: WorkerMessage = { type: 'cancel' };
|
||||
++generationIdRef.current;
|
||||
const message: WorkerRequestMessage = { type: 'cancel' };
|
||||
workerRef.current.postMessage(message);
|
||||
setIsGenerating(false);
|
||||
setProgress(null);
|
||||
|
||||
@@ -156,19 +156,29 @@ export interface GenerateProgress {
|
||||
}
|
||||
|
||||
/**
|
||||
* Worker 消息类型
|
||||
* Worker 请求消息类型
|
||||
*/
|
||||
export type WorkerMessage =
|
||||
export type WorkerRequestMessage =
|
||||
| { type: 'start'; payload: WorkerStartPayload }
|
||||
| { type: 'progress'; payload: GenerateProgress }
|
||||
| { type: 'complete'; payload: GenerateResult }
|
||||
| { type: 'error'; payload: { error: string } }
|
||||
| { type: 'cancel' };
|
||||
|
||||
/**
|
||||
* Worker 响应消息类型
|
||||
*/
|
||||
export type WorkerResponseMessage =
|
||||
| { type: 'progress'; generationId: number; payload: GenerateProgress }
|
||||
| { type: 'complete'; generationId: number; payload: GenerateResult }
|
||||
| { type: 'error'; generationId: number; payload: { error: string } };
|
||||
|
||||
/** @deprecated 使用 WorkerRequestMessage | WorkerResponseMessage */
|
||||
export type WorkerMessage = WorkerRequestMessage | WorkerResponseMessage;
|
||||
|
||||
/**
|
||||
* Worker 启动参数
|
||||
*/
|
||||
export interface WorkerStartPayload {
|
||||
/** 生成任务 ID,用于忽略过期 Worker 响应 */
|
||||
generationId: number;
|
||||
/** 字段配置列表 */
|
||||
fields: FieldConfig[];
|
||||
/** 生成数量 */
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
import { getGeneratorById } from '@/lib/generators';
|
||||
import type {
|
||||
FieldConfig,
|
||||
WorkerMessage,
|
||||
WorkerRequestMessage,
|
||||
GenerateResult,
|
||||
GenerateProgress,
|
||||
} from '@/types/testDataGenerator';
|
||||
|
||||
/** 每生成 N 行让出一次事件循环,以便处理 cancel 消息 */
|
||||
const YIELD_EVERY = 100;
|
||||
|
||||
// 生成结果缓存
|
||||
let generatedData: Record<string, unknown>[] = [];
|
||||
let isCancelled = false;
|
||||
@@ -18,7 +21,7 @@ let isCancelled = false;
|
||||
/**
|
||||
* Worker 消息处理器
|
||||
*/
|
||||
self.onmessage = async (e: MessageEvent<WorkerMessage>) => {
|
||||
self.onmessage = async (e: MessageEvent<WorkerRequestMessage>) => {
|
||||
const data = e.data;
|
||||
const { type } = data;
|
||||
|
||||
@@ -37,11 +40,12 @@ self.onmessage = async (e: MessageEvent<WorkerMessage>) => {
|
||||
* 处理开始生成消息
|
||||
*/
|
||||
async function handleStart(payload: {
|
||||
generationId: number;
|
||||
fields: FieldConfig[];
|
||||
count: number;
|
||||
csvMode: boolean;
|
||||
}): Promise<void> {
|
||||
const { fields, count } = payload;
|
||||
const { generationId, fields, count } = payload;
|
||||
generatedData = [];
|
||||
|
||||
try {
|
||||
@@ -51,6 +55,7 @@ async function handleStart(payload: {
|
||||
if (!generator) {
|
||||
self.postMessage({
|
||||
type: 'error',
|
||||
generationId,
|
||||
payload: { error: `生成器 "${field.generatorId}" 不存在` },
|
||||
});
|
||||
return;
|
||||
@@ -65,6 +70,7 @@ async function handleStart(payload: {
|
||||
if (isCancelled) {
|
||||
self.postMessage({
|
||||
type: 'complete',
|
||||
generationId,
|
||||
payload: {
|
||||
success: false,
|
||||
error: '生成已取消',
|
||||
@@ -136,7 +142,23 @@ async function handleStart(payload: {
|
||||
total: count,
|
||||
estimatedTimeLeft: Math.round(((Date.now() - startTime) / (i + 1)) * (count - i - 1)),
|
||||
};
|
||||
self.postMessage({ type: 'progress', payload: progress });
|
||||
self.postMessage({ type: 'progress', generationId, payload: progress });
|
||||
}
|
||||
|
||||
// 定期让出事件循环,使 cancel 消息能被处理
|
||||
if ((i + 1) % YIELD_EVERY === 0) {
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 0));
|
||||
if (isCancelled) {
|
||||
self.postMessage({
|
||||
type: 'complete',
|
||||
generationId,
|
||||
payload: {
|
||||
success: false,
|
||||
error: '生成已取消',
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,10 +177,11 @@ async function handleStart(payload: {
|
||||
},
|
||||
};
|
||||
|
||||
self.postMessage({ type: 'complete', payload: result });
|
||||
self.postMessage({ type: 'complete', generationId, payload: result });
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
type: 'error',
|
||||
generationId,
|
||||
payload: { error: `生成失败: ${error}` },
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user