How To Implement Worker Threads In Node.js

In this article, we will see How to implement Worker Threads in Node.js. After the release of Node.js V10.5.0, Worker Threads are available in the Node.js module. Before we dive into the Implementation of Worker threads in node.js, we will see what are worker threads and why we need it in Node.js

Threads and Node.js

If you are familiar with Javascript or getting started with it, you might have heard the term Single Threaded.

Javascript is a Single Threaded Programming language. The single thread is one thread which does all the operations of your code.

Since Node.js is built using Javascript V8 engine. it works in the same way. Javascript engine will be single thread and all the Operating system IO will happen in parallel. when it returns the results to Javascript code, it will be operated in a single thread.

Each and every operation you do will be handled by a single thread. IO Operations such as to request and response of a web server.

Single Thread Example Diagram
Single Thread Example Diagram

But, you can ask me, Node.js already handles everything with a single thread. then, why do we need Worker Threads in Node.js?

Actually, there are some situations where Node.js Single Thread doesn’t perform well. One of them is CPU Intensive Task.

CPU Intensive tasks are the one that blocks the main thread. when it happens, we can’t perform anything else in the application.

Possible Solutions

1. Child Process

To solve the problem of blocking the main thread in Node.js, we can use the concept of child process in Node.js

const { spawn } = require('child_process');

const child = spawn('pwd');

child.on('exit', function (code, signal) {
  console.log('child process exited with ' +
              `code ${code} and signal ${signal}`);
});

Problems of Child Process

  • Communication between the main process and child process is only through sending and receiving the message. processes won’t share the memory
  • The child process will have cloned data which means that changes in one process don’t reflect on another process
  • Forking process is resource expensive and it will be slow.

2. Worker Threads

Worker Threads can solve the problem of running CPU Intensive Tasks.

Worker Threads run in the same process. So, it will not lose the context of the process and No need to share Memory.

worker threads module will work on Node.js V10.5.0 or Higher, but keep in mind that this is in the experimental phase and can be changed frequently.

Worker Threads Example Diagram
Worker Threads Example Diagram

Implementation of Worker Threads

We will see how to implement worker threads in Node.js with a real-time use-case which is generating thumbnails of different sizes for an image.

create files called main.js, workerone.js and workertwo.js and add the following code in respective files.

main.js

const { Worker, isMainThread,  workerData } = require('worker_threads');

if(isMainThread) {
	    console.log("this is the main thread")
   
        
        let workerone = new Worker('./workerone.js',{ workerData: __dirname+'/original.jpg' });
    
        let workertwo = new Worker('./workertwo.js',{ workerData: __dirname+'/original.jpg' });

        workertwo.on('message',(data) => {
            console.log("message",data);
        })

        workertwo.on('error',(err) => {
            console.error(err);
        })
        workerone.on('message',(data) => {
            console.log("message",data)
        })
        
        workerone.on('error',(err) => {
            console.log(err);
        })

        workerone.on('exit',(code) => {
            if(code != 0) 
                console.error(`Worker stopped with exit code ${code}`)
        })
}

workerone.js

const imagemagick = require('imagemagick');

const { workerData,parentPort } = require('worker_threads');

let destSource = __dirname+'/one.jpg';
let optionObj = [workerData, '-resize', '100x100',destSource]
// console.log("workerData",workerData);
imagemagick.convert(optionObj,(err,stdout) => {
    if(err) throw err;


    parentPort.postMessage({ fileName: destSource,status : 'Done' })
})

workertwo.js

const imagemagick = require('imagemagick');

const { workerData,parentPort } = require('worker_threads');

let destSource = __dirname+'/two.jpg';
let optionObj = [workerData, '-resize', '200x200',destSource]
// console.log("workerData",workerData);
imagemagick.convert(optionObj,(err,stdout) => {
    if(err) throw err;


    parentPort.postMessage({ fileName: destSource,status : 'Done' })
})

  • Main.js – it checks whether it is the main thread or not. if it is, it creates two worker threads and passes the data to Worker Threads
  • workerone.js – it generates thumbnail and returns the data to the Main thread using parentPort.PostMessage.
  • workertwo.js – it will do the same process as like workerone.js but with different thumbnail size.

Complete Source Code can be found in this repository

Summary

Multi-Threading has been expected by the Node.js community for a long time. Worker threads are powerful and can solve the problem of multi-threading in Node.js. We can implement the CPU Intensive tasks in Node.js using Worker Threads rather than using child process in Node.js, due to the child processes downfalls.

SHARE ON
How To Implement Worker Threads In Node.js

You May Also Like

Leave a Reply

Your email address will not be published.