Bird
Raised Fist0
Node.jsframework~10 mins

Creating worker threads in Node.js - Visual Walkthrough

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Creating worker threads
Main Thread Starts
Create Worker Thread
Worker Thread Runs Code
Worker Sends Message to Main
Main Receives Message
Main and Worker Continue or Exit
The main thread creates a worker thread that runs code separately. They communicate by sending messages back and forth.
Execution Sample
Node.js
import { Worker } from 'node:worker_threads';

const worker = new Worker(`
  const { parentPort } = require('worker_threads');
  parentPort.postMessage('Hello from worker');
`, { eval: true });

worker.on('message', msg => console.log(msg));
This code creates a worker thread that sends a message to the main thread, which then logs it.
Execution Table
StepActionThreadMessage SentMessage ReceivedOutput
1Main thread startsMain
2Create worker thread with inline codeMain
3Worker thread starts running codeWorker
4Worker sends message 'Hello from worker'WorkerHello from worker
5Main thread receives messageMainHello from worker
6Main thread logs messageMainHello from worker
7Both threads continue or exitMain & Worker
💡 Execution stops after message is logged and no more code runs.
Variable Tracker
VariableStartAfter Step 2After Step 4After Step 5Final
workerundefinedWorker instance createdWorker runningMessage received event setWorker instance exists
Key Moments - 3 Insights
Why does the worker code run separately from the main thread?
Because the worker thread runs its own event loop and code independently, as shown in steps 3 and 4 where the worker sends a message without blocking the main thread.
How does the main thread get the message from the worker?
The main thread listens for the 'message' event on the worker object, as shown in step 5 where it receives 'Hello from worker'.
What does the { eval: true } option do when creating the worker?
It allows passing the worker code as a string to be evaluated, instead of loading from a separate file, as seen in step 2.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, at which step does the worker send a message to the main thread?
AStep 2
BStep 4
CStep 5
DStep 3
💡 Hint
Check the 'Message Sent' column in the execution table.
According to the variable tracker, what is the state of the 'worker' variable after step 2?
AUndefined
BMessage received event set
CWorker instance created
DWorker running
💡 Hint
Look at the 'After Step 2' column for 'worker' in the variable tracker.
If the main thread did not listen for messages, what would happen in the execution table?
AStep 5 would not show a message received
BStep 4 would not send a message
CStep 6 would log the message anyway
DWorker thread would not start
💡 Hint
Refer to the 'Message Received' column in the execution table.
Concept Snapshot
Creating worker threads in Node.js:
- Use 'Worker' from 'worker_threads' module
- Pass code or file to run in worker
- Workers run code separately from main thread
- Communicate via 'postMessage' and 'message' events
- Use { eval: true } to run inline code
- Main thread listens for messages to receive data
Full Transcript
In Node.js, creating worker threads lets you run code in parallel without blocking the main thread. The main thread creates a Worker instance, passing code to run. The worker runs independently and can send messages back to the main thread using postMessage. The main thread listens for these messages with the 'message' event. This allows communication between threads. Using the { eval: true } option lets you pass code as a string instead of a file. This example shows the main thread creating a worker that sends a greeting message, which the main thread logs. This way, heavy or blocking tasks can run in the worker without freezing the main program.

Practice

(1/5)
1. What is the main purpose of using worker_threads in Node.js?
easy
A. To handle HTTP requests faster
B. To simplify asynchronous callbacks
C. To manage database connections
D. To run code in parallel without blocking the main thread

Solution

  1. Step 1: Understand worker threads role

    Worker threads allow running JavaScript code in parallel threads separate from the main thread.
  2. Step 2: Compare with other options

    Options B, C, and D describe unrelated tasks; worker threads specifically help avoid blocking the main thread.
  3. Final Answer:

    To run code in parallel without blocking the main thread -> Option D
  4. Quick Check:

    Parallel code execution = A [OK]
Hint: Worker threads run code parallel to main thread [OK]
Common Mistakes:
  • Confusing worker threads with async callbacks
  • Thinking worker threads manage HTTP or DB tasks directly
2. Which of the following is the correct way to import the Worker class from the worker_threads module?
easy
A. const Worker = require('worker_threads');
B. import Worker from 'worker_threads';
C. const { Worker } = require('worker_threads');
D. const Worker = require('worker_threads').worker;

Solution

  1. Step 1: Recall correct import syntax

    The Worker class is a named export, so we use destructuring: const { Worker } = require('worker_threads');
  2. Step 2: Check other options

    const Worker = require('worker_threads'); assigns the entire module object, not the Worker class. import Worker from 'worker_threads'; uses ES module syntax which requires extra config. const Worker = require('worker_threads').worker; uses wrong property name.
  3. Final Answer:

    const { Worker } = require('worker_threads'); -> Option C
  4. Quick Check:

    Destructure Worker from module = D [OK]
Hint: Use destructuring to import Worker from worker_threads [OK]
Common Mistakes:
  • Using wrong property name like 'worker' instead of 'Worker'
  • Mixing CommonJS and ES module syntax incorrectly
3. What will be the output of the following code snippet?
const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename);
  worker.on('message', msg => console.log('From worker:', msg));
  worker.postMessage('Hello');
} else {
  parentPort.on('message', msg => {
    parentPort.postMessage(msg + ' World');
  });
}
medium
A. From worker: Hello World
B. From worker: Hello
C. SyntaxError
D. No output

Solution

  1. Step 1: Understand main and worker thread roles

    Main thread creates a worker running the same file. It sends 'Hello' to worker.
  2. Step 2: Trace message passing

    Worker receives 'Hello', appends ' World', and sends back 'Hello World'. Main thread logs this message.
  3. Final Answer:

    From worker: Hello World -> Option A
  4. Quick Check:

    Message sent + ' World' logged = B [OK]
Hint: Worker appends ' World' and sends back message [OK]
Common Mistakes:
  • Expecting original message without modification
  • Confusing main thread and worker thread roles
  • Missing event listeners for messages
4. Identify the error in this worker thread code snippet:
const { Worker } = require('worker_threads');

const worker = new Worker('worker.js');
worker.on('message', msg => console.log(msg));
worker.postMessage('Start');
medium
A. Worker file path should be absolute or URL
B. Missing event listener for 'error' event
C. Cannot create Worker with a string filename
D. Cannot call postMessage on Worker instance

Solution

  1. Step 1: Check Worker constructor argument

    The Worker constructor expects an absolute path or a URL, not just a relative string like 'worker.js'.
  2. Step 2: Validate other options

    Cannot create Worker with a string filename is incorrect because Worker can be created with a filename if path is correct. Missing event listener for 'error' event is good practice but not an error. Cannot call postMessage on Worker instance is wrong; postMessage is valid on Worker.
  3. Final Answer:

    Worker file path should be absolute or URL -> Option A
  4. Quick Check:

    Worker needs absolute path or URL = C [OK]
Hint: Use absolute path or URL for Worker file [OK]
Common Mistakes:
  • Using relative paths without resolving them
  • Ignoring error event listeners
  • Thinking postMessage is invalid on Worker
5. You want to create a worker thread that performs a CPU-heavy calculation and sends the result back. Which approach correctly creates the worker and handles the result asynchronously?
hard
A. Use new Worker() without arguments and call worker.send() to communicate
B. Use new Worker('./calc.js') with worker.on('message', callback) and send data via worker.postMessage()
C. Use require('worker_threads').run() to start the worker and get a promise
D. Create a child process with child_process.fork() and communicate with worker.postMessage()

Solution

  1. Step 1: Identify correct Worker creation and communication

    Creating a worker with new Worker('./calc.js') and using worker.on('message') plus worker.postMessage() is the standard pattern.
  2. Step 2: Eliminate incorrect options

    Use new Worker() without arguments and call worker.send() to communicate is invalid because Worker requires a filename or code. Use require('worker_threads').run() to start the worker and get a promise is incorrect; no run() method exists. Create a child process with child_process.fork() and communicate with worker.postMessage() uses child_process, not worker_threads, and postMessage is not valid on child processes.
  3. Final Answer:

    Use new Worker('./calc.js') with worker.on('message', callback) and send data via worker.postMessage() -> Option B
  4. Quick Check:

    Worker with filename + message events = A [OK]
Hint: Use new Worker(filename) and message events for communication [OK]
Common Mistakes:
  • Trying to create Worker without filename
  • Confusing child_process with worker_threads
  • Using non-existent Worker methods