Tips & Tricks

Claude Code के साथ Web Worker Implementation

Claude Code का उपयोग करके web worker implementation सीखें। Practical tips और code examples शामिल हैं।

Web Workerがज़रूरीな場面

JavaScriptはシングルthreadで動作するため、重い計算processingはUIをフリーズさせ है।Web Workerを使えば、バックグラウンドthreadでprocessingを実行し、メインthreadの応答性を維持でき है।Claude Code का उपयोग करके、型safeなWeb Worker通信の仕組みを素早くbuild किया जा सकता है。

型safeなWeb Worker通信

> TypeScriptで型safeなWeb Workerの通信レイヤーを作って。
> messageのtype definitionsとPromiseベースの呼び出しにsupportして。
// worker-types.ts
export interface WorkerRequest {
  id: string;
  type: string;
  payload: any;
}

export interface WorkerResponse {
  id: string;
  result?: any;
  error?: string;
}

// typed-worker.ts
type MessageHandler = (payload: any) => any | Promise<any>;

class TypedWorkerHost {
  private worker: Worker;
  private pending = new Map<string, { resolve: Function; reject: Function }>();
  private counter = 0;

  constructor(workerUrl: string | URL) {
    this.worker = new Worker(workerUrl, { type: 'module' });
    this.worker.onmessage = (e: MessageEvent<WorkerResponse>) => {
      const { id, result, error } = e.data;
      const handler = this.pending.get(id);
      if (!handler) return;
      this.pending.delete(id);
      error ? handler.reject(new Error(error)) : handler.resolve(result);
    };
  }

  call<T>(type: string, payload: any): Promise<T> {
    return new Promise((resolve, reject) => {
      const id = `msg-${++this.counter}`;
      this.pending.set(id, { resolve, reject });
      this.worker.postMessage({ id, type, payload } satisfies WorkerRequest);
    });
  }

  terminate() {
    this.worker.terminate();
    this.pending.forEach(({ reject }) => reject(new Error('Worker terminated')));
    this.pending.clear();
  }
}

worker側のimplementation

// heavy-computation.worker.ts
const handlers: Record<string, (payload: any) => any> = {
  'sort-data': (data: number[]) => {
    return data.sort((a, b) => a - b);
  },

  'filter-search': ({ items, query }: { items: any[]; query: string }) => {
    return items.filter((item) =>
      Object.values(item).some((v) =>
        String(v).toLowerCase().includes(query.toLowerCase())
      )
    );
  },

  'compute-statistics': (data: number[]) => {
    const n = data.length;
    const mean = data.reduce((a, b) => a + b, 0) / n;
    const sorted = [...data].sort((a, b) => a - b);
    const median = n % 2 === 0
      ? (sorted[n / 2 - 1] + sorted[n / 2]) / 2
      : sorted[Math.floor(n / 2)];
    const variance = data.reduce((sum, x) => sum + (x - mean) ** 2, 0) / n;

    return { mean, median, stdDev: Math.sqrt(variance), min: sorted[0], max: sorted[n - 1] };
  },
};

self.onmessage = async (e: MessageEvent<WorkerRequest>) => {
  const { id, type, payload } = e.data;

  try {
    const handler = handlers[type];
    if (!handler) throw new Error(`Unknown handler: ${type}`);
    const result = await handler(payload);
    self.postMessage({ id, result });
  } catch (error: any) {
    self.postMessage({ id, error: error.message });
  }
};

workerプール

> 複数のWorkerをmanagementするプールを作って。taskを効率よく分散して。
class WorkerPool {
  private workers: TypedWorkerHost[] = [];
  private queue: { type: string; payload: any; resolve: Function; reject: Function }[] = [];
  private busy: Set<number> = new Set();

  constructor(workerUrl: string, poolSize: number = navigator.hardwareConcurrency || 4) {
    for (let i = 0; i < poolSize; i++) {
      this.workers.push(new TypedWorkerHost(new URL(workerUrl, import.meta.url)));
    }
  }

  async execute<T>(type: string, payload: any): Promise<T> {
    const freeIndex = this.workers.findIndex((_, i) => !this.busy.has(i));

    if (freeIndex === -1) {
      return new Promise((resolve, reject) => {
        this.queue.push({ type, payload, resolve, reject });
      });
    }

    return this.runOnWorker(freeIndex, type, payload);
  }

  private async runOnWorker<T>(index: number, type: string, payload: any): Promise<T> {
    this.busy.add(index);
    try {
      return await this.workers[index].call<T>(type, payload);
    } finally {
      this.busy.delete(index);
      this.processQueue();
    }
  }

  private processQueue() {
    if (this.queue.length === 0) return;
    const freeIndex = this.workers.findIndex((_, i) => !this.busy.has(i));
    if (freeIndex === -1) return;

    const task = this.queue.shift()!;
    this.runOnWorker(freeIndex, task.type, task.payload)
      .then(task.resolve)
      .catch(task.reject);
  }

  terminate() {
    this.workers.forEach((w) => w.terminate());
  }
}

Reacthookでのutilization

function useWorker<T>(type: string, payload: any, deps: any[]) {
  const [result, setResult] = useState<T | null>(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    pool.execute<T>(type, payload)
      .then(setResult)
      .finally(() => setLoading(false));
  }, deps);

  return { result, loading };
}

Summary

Claude Code का उपयोग करके、型safeなWeb Worker通信 सेworkerプール तक、並列processing基盤をefficientlybuild किया जा सकता है。performance全般はperformanceoptimizationを、Service Workerとの違いはService Workerutilizationをदेखें。

Web Worker APIの仕様はMDN Web Docs - Web Workersदेखें。

#Claude Code #Web Worker #並列processing #performance #TypeScript