Skip to content

A React hook for easy Web Worker integration with TypeScript support.

Notifications You must be signed in to change notification settings

CoderSerio/useWebWorker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

bd9ce39 · Apr 8, 2025

History

24 Commits
Mar 28, 2025
Apr 8, 2025
Mar 28, 2025
Apr 3, 2025
Mar 28, 2025
Mar 28, 2025
Apr 7, 2025
Apr 7, 2025
Mar 28, 2025
Mar 28, 2025
Apr 3, 2025
Mar 24, 2025
Mar 28, 2025

Repository files navigation

useWebWorker

NPM version NPM downloads

English | 中文

A React hook for easy Web Worker integration with TypeScript support.

Features

  • 🚀 Simple API for Web Worker management
  • 💪 Full TypeScript support with automatic type inference
  • 🔄 Automatic cleanup on unmount
  • ⚡ Non-blocking UI operations
  • 📦 Zero dependencies
  • ⏱️ Built-in timeout handling
  • 🔍 Comprehensive error handling
  • 📊 Progress reporting and custom message passing
  • 🎯 Function-based worker creation - No additional files needed - write your worker logic inline

Installation

npm install @atom-universe/use-web-worker
# or
pnpm add @atom-universe/use-web-worker
# or
yarn add @atom-universe/use-web-worker

Usage

import useWebWorker from '@atom-universe/use-web-worker';
import { useState } from 'react';

function Example() {
  const [progress, setProgress] = useState(0);

  const [workerFn, workerStatus, workerTerminate] = useWebWorker(
    (data, workerContext) => {
      const total = data.length;
      const result = [];

      for (let i = 0; i < total; i++) {
        result.push(data[i] * 2);
        // Report progress every 10%
        if (i % Math.floor(total / 10) === 0) {
          const percentComplete = Math.floor((i / total) * 100);
          workerContext.postMessage(['PROGRESS', { percent: percentComplete }]);
        }
      }

      return result;
    },
    {
      timeout: 30000, // 30 seconds timeout
      onError: error => {
        console.error('Computation error:', error);
      },
      onMessage: message => {
        // Handle progress updates
        if (message.type === 'PROGRESS') {
          setProgress(message.data.percent);
        }
      },
    }
  );

  const handleProcess = async () => {
    try {
      // Generate array with 1000 items
      const data = Array.from({ length: 1000 }, (_, i) => i);
      const result = await workerFn(data);
      console.log('Result:', result);
    } catch (error) {
      console.error('Failed to process:', error);
    }
  };

  return (
    <div>
      <button onClick={handleProcess} disabled={workerStatus === 'RUNNING'}>
        {workerStatus === 'RUNNING' ? 'Processing...' : 'Start Process'}
      </button>

      {workerStatus === 'RUNNING' && (
        <button onClick={() => workerTerminate('PENDING')}>Cancel</button>
      )}

      {workerStatus === 'RUNNING' && (
        <div>
          <p>Progress: {progress}%</p>
          <div
            style={{
              width: '100%',
              backgroundColor: '#e9ecef',
              borderRadius: '4px',
              height: '20px',
            }}
          >
            <div
              style={{
                width: `${progress}%`,
                backgroundColor: '#007bff',
                height: '100%',
              }}
            />
          </div>
        </div>
      )}
    </div>
  );
}

API

function useWebWorker<T extends (...args: any[]) => any>(
  fn: T,
  options?: {
    timeout?: number; // Timeout in milliseconds
    dependencies?: string[]; // External dependencies
    localDependencies?: Function[]; // Local function dependencies
    onError?: (error: Error) => void; // Error callback
    onMessage?: (message: { type: string; data: any }) => void; // Custom message handler
  }
): [
  (...args: Parameters<T>) => Promise<ReturnType<T>>, // Worker function
  'PENDING' | 'RUNNING' | 'SUCCESS' | 'ERROR' | 'TIMEOUT_EXPIRED', // Status
  (status?: WebWorkerStatus) => void, // Terminate function
];

License

MIT