( file: File, config: OptimizerConfiguration, )
| 46 | * Wraps the Worker's event-based API in a clean Promise. |
| 47 | */ |
| 48 | export const processImageInWorker = ( |
| 49 | file: File, |
| 50 | config: OptimizerConfiguration, |
| 51 | ): Promise<{buffer: ArrayBuffer; time: number}> => { |
| 52 | // Executor function must be synchronous. We wrap async logic in an IIFE. |
| 53 | return new Promise((resolve, reject) => { |
| 54 | const worker = getWorkerFromPool(); |
| 55 | |
| 56 | // Register the task as active |
| 57 | activeTasks.set(worker, {resolve, reject}); |
| 58 | |
| 59 | // Use 'void' to satisfy @typescript-eslint/no-floating-promises |
| 60 | void (async () => { |
| 61 | try { |
| 62 | const buffer = await file.arrayBuffer(); |
| 63 | |
| 64 | // Check if cancelled during the async arrayBuffer read |
| 65 | if (!activeTasks.has(worker)) { |
| 66 | // Task was cancelled externally. |
| 67 | return; |
| 68 | } |
| 69 | |
| 70 | // Listen for the worker's reply |
| 71 | worker.onmessage = (event: MessageEvent<WorkerResponseMessage>) => { |
| 72 | const {type, buffer: resBuffer, time, message, details} = event.data; |
| 73 | |
| 74 | if (activeTasks.has(worker)) { |
| 75 | if (type === 'SUCCESS' && resBuffer) { |
| 76 | activeTasks.delete(worker); |
| 77 | resolve({buffer: resBuffer, time: time || 0}); |
| 78 | returnWorkerToPool(worker); |
| 79 | } else if (type === 'ERROR') { |
| 80 | activeTasks.delete(worker); |
| 81 | console.error('[Worker Error Details]:', details); |
| 82 | reject(new Error(message || 'Unknown worker error')); |
| 83 | returnWorkerToPool(worker); |
| 84 | } else if (type === 'LOG') { |
| 85 | console.debug(message, details); |
| 86 | } |
| 87 | } |
| 88 | }; |
| 89 | |
| 90 | // Handle crashes |
| 91 | worker.onerror = error => { |
| 92 | if (activeTasks.has(worker)) { |
| 93 | activeTasks.delete(worker); |
| 94 | console.error('Worker Global Error', error); |
| 95 | reject(error); |
| 96 | worker.terminate(); // Kill dead workers |
| 97 | } |
| 98 | }; |
| 99 | |
| 100 | // Send data to worker |
| 101 | worker.postMessage( |
| 102 | { |
| 103 | buffer, |
| 104 | fileType: file.type, |
| 105 | config, |
no test coverage detected