Concurrency and Multithreading in TypeScript: Advanced Level

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Concurrency and Multithreading in TypeScript: Advanced Level

\n\n

In modern web development and server-side programming, application performance and responsiveness are critically important. TypeScript, being a superset of JavaScript, inherited its single-threaded execution model (Event Loop). However, for solving resource-intensive tasks (image processing, cryptography, complex calculations), asynchrony alone is not enough. At an advanced level, a developer needs to understand how to organize true multithreading and safe work with shared memory. In this article, we will analyze key mechanisms: Web Workers (browser), Worker Threads (Node.js), SharedArrayBuffer, and Atomics.

\n\n

1. Web Workers: Parallelism in the Browser

\n\n

Web Workers are the primary way to run code in a separate thread in a browser environment. A Worker does not have access to the DOM, but can perform heavy computations without blocking the main (UI) thread.

\n\n

Creating a Worker in TypeScript requires compiling a separate file. Let's look at an example: calculating large Fibonacci numbers.

\n\n

File worker.ts (compiles to worker.js):

\n
// worker.ts\nself.onmessage = (event: MessageEvent<number>) => {\n  const n = event.data;\n  const fib = (num: number): number => {\n    if (num <= 1) return num;\n    return fib(num - 1) + fib(num - 2);\n  };\n  const result = fib(n);\n  self.postMessage(result);\n};
\n\n

File main.ts:

\n
// main.ts\nconst worker = new Worker(new URL('./worker.js', import.meta.url));\n\nworker.postMessage(40);\n\nworker.onmessage = (event: MessageEvent<number>) => {\n  console.log(`Result: ${event.data}`); // Output after completion\n  worker.terminate();\n};\n\nworker.onerror = (error) => {\n  console.error('Worker error:', error.message);\n};
\n\n

Important nuances:

\n
    \n
  • The Worker runs in a separate thread but does not have access to the global variables of the main thread.
  • \n
  • Data transfer occurs via copying (structured cloning). For large data, use Transferable objects (e.g., ArrayBuffer).
  • \n
  • For TypeScript, it is mandatory to specify types in messages to avoid runtime errors.
  • \n
\n\n

2. Worker Threads: Multithreading in Node.js

\n\n

For the server-side Node.js environment, the equivalent of Web Workers is the worker_threads module. It allows creating isolated threads with their own memory (V8 isolate). This is ideal for CPU-intensive operations such as hashing or JSON parsing.

\n\n

Example: Creating a Worker for password hashing (worker.ts):

\n
// crypto-worker.ts\nimport { parentPort, workerData } from 'worker_threads';\nimport { createHash } from 'crypto';\n\nif (parentPort) {\n  const { password, salt } = workerData;\n  const hash = createHash('sha256')\n    .update(password + salt)\n    .digest('hex');\n  parentPort.postMessage(hash);\n}
\n\n

Main file (main.ts):

\n
// main.ts\nimport { Worker } from 'worker_threads';\nimport path from 'path';\n\nfunction hashPassword(password: string, salt: string): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const worker = new Worker(path.resolve(__dirname, 'crypto-worker.js'), {\n      workerData: { password, salt }\n    });\n\n    worker.on('message', resolve);\n    worker.on('error', reject);\n    worker.on('exit', (code) => {\n      if (code !== 0) reject(new Error(`Worker exited with code ${code}`));\n    });\n  });\n}\n\n(async () => {\n  const hash = await hashPassword('mySecret', 'randomSalt');\n  console.log(`Hash: ${hash}`);\n})();
\n\n

Key differences from Web Workers:

\n
    \n
  • Runs in Node.js, has access to the file system and process.
  • \n
  • Data transfer via

Blogs

Book Recommendations