← Back to Home

Web Worker Pool

Up to 10 connected users — each interaction is processed by a background worker thread, keeping the UI thread free.

0
Connected users
10
Worker pool size
0
Messages processed
0
Worker tasks run
Connected users 0 / 10
Activity feed
Send message as: — select a user —

How it works

A WorkerPool of 10 inline workers is created once on page load. When a user sends a message, the task is dispatched to the next worker in round-robin fashion — keeping the main thread unblocked regardless of how many users are active simultaneously.

// ── Inline WorkerPool (no separate file needed) ──────────────────────

function createWorkerPool(workerFn, size = 10) {
  const slots = Array.from({ length: size }, (_, i) => {
    const blob = new Blob([
      `self.onmessage = (e) => {
        const taskId = e.data && e.data.__taskId;
        try {
          const result = (${workerFn.toString()})(e, ${i});
          self.postMessage({ __taskId: taskId, result });
        } catch (err) {
          self.postMessage({ __taskId: taskId, error: err && err.message ? err.message : String(err) });
        }
      }`
    ], { type: 'application/javascript' });
    const url = URL.createObjectURL(blob);
    const worker = new Worker(url, { type: 'classic' });
    URL.revokeObjectURL(url); // safe to revoke after construction

    const pending = new Map();
    worker.onmessage = (e) => {
      const { __taskId, result, error } = e.data || {};
      const callbacks = pending.get(__taskId);
      if (!callbacks) return;
      pending.delete(__taskId);
      if (error) callbacks.reject(new Error(error));
      else callbacks.resolve(result);
    };

    return { worker, pending };
  });

  let index = 0;
  let taskId = 0;

  return {
    send(data) {
      const slot = slots[index++ % size];
      const currentTaskId = ++taskId;
      return new Promise((resolve, reject) => {
        slot.pending.set(currentTaskId, { resolve, reject });
        slot.worker.postMessage({ ...data, __taskId: currentTaskId });
      });
    },
    terminate() { slots.forEach(({ worker }) => worker.terminate()); },
  };
}

// ── Worker function (runs in background thread) ───────────────────────

function processMessage(event, workerId) {
  const { userId, text } = event.data;
  // Simulate processing (e.g. sanitise, filter, analyse sentiment …)
  const wordCount = text.trim().split(/\s+/).filter(Boolean).length;
  const charCount = text.length;
  return { userId, wordCount, charCount, workerId };
}

// ── Usage ─────────────────────────────────────────────────────────────

const pool = createWorkerPool(processMessage, 10);

const result = await pool.send({ userId: 'alice', text: 'Hello world!' });
// → { userId: 'alice', wordCount: 2, charCount: 12, workerId: 0 }

Documentation

Next Step