UNPKG

id-scanner-lib

Version:

Browser-based ID card, QR code, and face recognition scanner with liveness detection

130 lines (121 loc) 3.19 kB
/** * @file WorkerBridge - Web Worker 并行处理框架 * @description 提供基于 Promise 的 Worker 通信接口,支持超时和错误处理 * @module core/utils/worker */ /** * Worker 消息格式 */ export type WorkerMessage<T = any> = { type: string; payload: T; id: string; }; /** * Worker 响应格式 */ export type WorkerResponse<T = any> = { type: string; payload: T; error?: string; id: string; }; /** * WorkerBridge - 基于 Promise 的 Worker 通信桥接器 * * 提供简洁的 Worker 消息发送接口,自动处理请求-响应匹配、超时和错误 * * @example * ```typescript * const bridge = new WorkerBridge('/workers/face-detect.worker.ts'); * await bridge.load(); * const result = await bridge.post('detect', { imageData }); * bridge.terminate(); * ``` */ export class WorkerBridge<TReq = any, TRes = any> { private _worker: Worker | null = null; private _pending: Map<string, { resolve: Function; reject: Function }> = new Map(); private _url: string; /** * 创建 WorkerBridge * @param workerUrl Worker 文件 URL */ constructor(workerUrl: string) { this._url = workerUrl; } /** * 加载 Worker */ async load(): Promise<void> { this._worker = new Worker(this._url); this._worker.onmessage = (e: MessageEvent<WorkerResponse<TRes>>) => { const { id, payload, error } = e.data; const handlers = this._pending.get(id); if (handlers) { if (error) { handlers.reject(new Error(error)); } else { handlers.resolve(payload); } this._pending.delete(id); } }; this._worker.onerror = (e) => { // 将 Worker 错误广播给所有 pending 的 Promise for (const [id, handlers] of this._pending) { handlers.reject(new Error(`Worker error: ${e.message}`)); this._pending.delete(id); } }; } /** * 发送消息到 Worker 并等待响应 * * @param type 消息类型 * @param payload 消息载荷 * @returns 响应 Promise * @throws 如果 Worker 未加载则抛出错误 */ async post(type: string, payload: TReq): Promise<TRes> { if (!this._worker) { throw new Error('Worker not loaded'); } const id = crypto.randomUUID(); return new Promise((resolve, reject) => { this._pending.set(id, { resolve, reject }); this._worker!.postMessage({ type, payload, id } as WorkerMessage<TReq>); // 超时 30s setTimeout(() => { if (this._pending.has(id)) { this._pending.delete(id); reject(new Error('Worker timeout')); } }, 30000); }); } /** * 终止 Worker */ terminate(): void { this._worker?.terminate(); this._worker = null; // 拒绝所有 pending 的 Promise for (const [, handlers] of this._pending) { handlers.reject(new Error('Worker terminated')); } this._pending.clear(); } /** * 检查 Worker 是否已加载 */ get isLoaded(): boolean { return this._worker !== null; } /** * 获取当前 pending 请求数 */ get pendingCount(): number { return this._pending.size; } }