乐闻世界logo
搜索文章和话题

How to debug Web Worker?

2月21日 15:10

Debugging Web Workers is more challenging than debugging the main thread, but there are various tools and techniques to help developers efficiently debug Worker code.

Chrome DevTools Debugging

1. View Worker Threads

  1. Open Chrome DevTools (F12)
  2. Switch to "Sources" panel
  3. Find "Threads" or "Workers" section on the left
  4. Select the corresponding Worker thread for debugging

2. Set Breakpoints in Worker

javascript
// worker.js self.onmessage = function(e) { const data = e.data; // Set breakpoint here const result = processData(data); self.postMessage(result); }; function processData(data) { // Can set breakpoint here to view variables let sum = 0; for (let i = 0; i < data.length; i++) { sum += data[i]; } return sum; }

3. Use console.log

javascript
// worker.js self.onmessage = function(e) { console.log('[Worker] Received message:', e.data); const result = heavyComputation(e.data); console.log('[Worker] Computation result:', result); self.postMessage(result); };

Firefox Developer Tools

1. Debug Worker

  1. Open Firefox Developer Tools (F12)
  2. Switch to "Debugger" panel
  3. Find "Workers" section on the left
  4. Expand and select the Worker to debug

2. Worker Console

javascript
// worker.js // In Firefox, Worker's console.log appears in main console console.log('Worker message'); // Can also use Worker-specific debug info self.postMessage({ type: 'debug', message: 'Debug info' });

Debugging Techniques

1. Message Tracking

javascript
// Main thread const worker = new Worker('worker.js'); // Add message send tracking const originalPostMessage = worker.postMessage.bind(worker); worker.postMessage = function(data) { console.log('[Main → Worker]', data); return originalPostMessage(data); }; // Add message receive tracking worker.addEventListener('message', function(e) { console.log('[Worker → Main]', e.data); });

2. Error Capture

javascript
// Main thread worker.onerror = function(event) { console.error('Worker Error:'); console.error('Message:', event.message); console.error('Filename:', event.filename); console.error('Line:', event.lineno); console.error('Column:', event.colno); console.error('Error Object:', event.error); }; // Inside Worker self.onerror = function(event) { console.error('Worker Internal Error:', event.message); // Can choose not to prevent default behavior // event.preventDefault(); }; // Use try-catch self.onmessage = function(e) { try { const result = riskyOperation(e.data); self.postMessage(result); } catch (error) { console.error('Error in message handler:', error); self.postMessage({ error: error.message, stack: error.stack }); } };

3. Performance Analysis

javascript
// worker.js self.onmessage = function(e) { const startTime = performance.now(); const result = heavyComputation(e.data); const endTime = performance.now(); const duration = endTime - startTime; console.log(`[Worker] Computation took ${duration.toFixed(2)}ms`); self.postMessage({ result, duration }); };

4. State Monitoring

javascript
// worker.js let state = { messageCount: 0, totalProcessingTime: 0, lastMessageTime: null }; self.onmessage = function(e) { const startTime = performance.now(); state.messageCount++; state.lastMessageTime = new Date().toISOString(); const result = processMessage(e.data); const endTime = performance.now(); state.totalProcessingTime += (endTime - startTime); self.postMessage({ result, state }); }; // Periodically report state setInterval(() => { console.log('[Worker] State:', state); }, 5000);

Advanced Debugging Techniques

1. Use Source Map

javascript
// Add source map in Worker script // worker.js // # sourceMappingURL=worker.js.map // Or specify when creating Worker const worker = new Worker('worker.js'); worker.addEventListener('message', function(e) { console.log(e.data); });

2. Conditional Breakpoints

Set conditional breakpoints in Chrome DevTools:

javascript
// Set conditional breakpoint in processData function // Condition: data.length > 1000 function processData(data) { let sum = 0; for (let i = 0; i < data.length; i++) { sum += data[i]; } return sum; }

3. Log Levels

javascript
// worker.js const LogLevel = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 }; let currentLogLevel = LogLevel.INFO; function log(level, message, data) { if (level >= currentLogLevel) { const prefix = { [LogLevel.DEBUG]: '[DEBUG]', [LogLevel.INFO]: '[INFO]', [LogLevel.WARN]: '[WARN]', [LogLevel.ERROR]: '[ERROR]' }[level]; console.log(`${prefix} ${message}`, data || ''); } } self.onmessage = function(e) { log(LogLevel.DEBUG, 'Received message', e.data); try { const result = processData(e.data); log(LogLevel.INFO, 'Processing complete', { result }); self.postMessage(result); } catch (error) { log(LogLevel.ERROR, 'Processing failed', { error: error.message }); } };

4. Message Serialization Check

javascript
// Check if message can be correctly serialized function checkSerializable(data) { try { const cloned = structuredClone(data); console.log('[Worker] Data is serializable'); return true; } catch (error) { console.error('[Worker] Data is not serializable:', error); return false; } } self.onmessage = function(e) { if (!checkSerializable(e.data)) { self.postMessage({ error: 'Data is not serializable' }); return; } // Process message };

Debugging Tools and Libraries

1. Worker DevTools Extension

Using Chrome extension "Worker DevTools" allows:

  • View Worker's console output
  • Check Worker's network requests
  • Monitor Worker's performance

2. Use Debug Proxy

javascript
// debug-worker.js const originalWorker = self.Worker; self.Worker = function(scriptURL) { console.log('[Debug] Creating Worker:', scriptURL); const worker = new originalWorker(scriptURL); const originalPostMessage = worker.postMessage.bind(worker); worker.postMessage = function(data) { console.log('[Debug] Main → Worker:', data); return originalPostMessage(data); }; worker.addEventListener('message', function(e) { console.log('[Debug] Worker → Main:', e.data); }); return worker; };

Common Issue Troubleshooting

1. Worker Won't Start

javascript
// Check Worker file path const worker = new Worker('/workers/worker.js'); // Ensure path is correct // Check browser support if (typeof Worker === 'undefined') { console.error('Web Workers are not supported in this browser'); } // Check same-origin policy // Ensure Worker script is same-origin with main page

2. Messages Not Arriving

javascript
// Check if port is started (SharedWorker) const sharedWorker = new SharedWorker('worker.js'); sharedWorker.port.start(); // Must call start() // Check message format // Ensure message can be structured cloned

3. Memory Leaks

javascript
// Use Chrome DevTools Memory panel // 1. Take heap snapshot // 2. Perform operations // 3. Take another heap snapshot // 4. Compare two snapshots, find memory growth // Release references in Worker self.onmessage = function(e) { const result = process(e.data); self.postMessage(result); e.data = null; // Release reference };

Best Practices

  1. Use Meaningful Logs: Add clear log messages
  2. Error Handling: Add error handling in both Worker and main thread
  3. Performance Monitoring: Monitor Worker execution time and resource usage
  4. Message Tracking: Track message sending and receiving
  5. Use Debug Tools: Fully utilize browser developer tools
  6. Conditional Breakpoints: Use conditional breakpoints to reduce debugging time
  7. Log Levels: Use different log levels to filter information
  8. Regular Checks: Regularly check Worker status and performance
标签:Web Worker