Getting Started with Node.js Child Processes

In this tutorial, we will discuss how to we can use child processes to launch another process to avoid delays while executing our programs.

1. Introduction

Node.js programs run on a single thread when executed. Executing millions of processes leads to delays/blocking hence the need for a solution. One way to work around this delay is the use of the Node.js child process.

2. Prerequisites

This tutorial requires basic knowledge of JavaScript and Node.js.

3. Getting started

Node.js is single-threaded, implying that however powerful your server is, it only supports a few loads at a given time. This is where child processes come in. They help in working around these delays hence improving the general program performance.

4. Child process module

The child process module has several methods that we can use to create other processes.

In this tutorial, we cover the following 2 major methods:

  1. child_process.exec()
  2. child_process.spawn()

5. Creating child process using exec() method

The child_process.exec() method creates a new shell process. It then uses this shell to execute commands. The output of these executed commands is then kept in an in-memory buffer.

This output can then be accessed via the callback function that is being passed to the exec() method. Let’s look at an example:

NOTE: In this tutorial, we use the Node.js powerful [REPL](https://nodejs.dev/learn/how-to-use-the-nodejs-repl) command-line tool to run/test our results, but you’re free to create files to suit your requirements.

Launch your REPL by running the following command in your terminal:

$ node

Output:

$ node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> 

Next, let’s import the child_process module by running the following command:

...................
> const {exec} = require('child_process');
undefined
> 

Let’s proceed and log to our console exec constant.

Output:

> const {exec} = require(`child_process`);
undefined
> console.log(exec);
[Function: exec]   //output
undefined
> 

You notice that exec constant is of type Function object.

Let’s now have a look at child_process.exec()method syntax:

child_process.exec(command[, options][, callback])

This method takes 2 arguments, command as the first argument with optional options and a callback function. The command argument is of type string, that expects a command to execute, say, for example, a command to list your directory’s files.

The options is an object, that takes several other additional methods, for instance, getting the current working directory of the child process process.cwd(). The callback is a function that should be called when a process has been terminated.

It takes the 3 arguments as follows:

  • error – returns an error of type Error.
  • stdout | – returns a string or a buffer, handling binary data.
  • stderr | – returns a string/ buffer.

Now that we’ve covered the basics on how this method works, let’s look at a working example.

In your REPL , add the following scripts to execute the ls command listing folders and files in your current directory:

> exec('ls -lh', (error, stdout, stderr) => {
...   if (err) {
.....     console.error(err);
.....     return;
.....   }
... 
...   if (stderr) {
...     console.error(stderr);
...     return;
...   }
... 
...   console.log(stdout);
... });
>  
undefined
> 

Output:

> stdout:
total 8.0K
-rwxrwxrwx 1 root       root        612 Apr  2 11:57 index.nginx-debian.html
lrwxrwxrwx 1 root       root         21 Apr  2 12:54 phpmyadmin -> /usr/share/phpmyadmin
drwxrwxr-x 5 wen wen 4.0K Apr  2 12:24 project

From the script above:
We first import the child_process module, using an extremely terse syntax, the JavaScript destructuring.

child_process.exec() expects 2 arguments, command and the callback function. The callback function takes 3 arguments, errorstdout, and stderr.

On successful execution, error returns null otherwise an instance of Error is returned.

The stdout and stderr contain the child process’ output decoded in UTF-8as shown in the output above.

6. Creating child process using ‘child_process.spawn()’

Unlike the child_process.exec(), this method requires the use of the streams i.e data is returned via the streams API.

Therefore, to get the required results, we listen to stream events.

Let’s look at an example:

In your REPL, run the following commands:

Type ".help" for more information.
> const { spawn } = require('child_process');
undefined
> 
> const spawned_child = spawn('cat', ['child.js']);
undefined
> 

In the script above, we first import the child_process module. The result is assigned to a destructured constant, spawn.

We then create a child process by calling the spawn() method. This method accepts 2 arguments, the command, and optional options.

The resulting output is assigned to a spawned_child constant.

It’s also important to note that the spawn function call will always return ChildProcess instance.

$ node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> const fs = require('fs')
undefined
> const { spawn } = require('child_process')
undefined
> const filename ='child.js'
undefined
> 
> fs.watch(filename, () => {
...   const ls = spawn('ls', ['-lh', filename])
...   ls.stdout.pipe(process.stdout)
... })
<ref *1> FSWatcher {
  _events: [Object: null prototype] { change: [Function (anonymous)] },
  _eventsCount: 1,
  _maxListeners: undefined,
  _handle: FSEvent {
    onchange: [Function (anonymous)],
    [Symbol(owner_symbol)]: [Circular *1]
  },
  [Symbol(kCapture)]: false
}

In the script above, we’ve created a file child.js. We’re watching this file for changes i.e edits or deletions. Whenever a change has been made, we run the command ls -lh.

We then proceed to pipe our output from the main process from the child process.

Note that no output will be displayed if we don’t pipe out result from the main process

7. Conclusion

In this tutorial, we’ve seen how we can create child process using the child_process.exec() and child_process.spawn().

Other methods exists such as child_process.fork() which is a variation of the child_process.spawn() method.

For more details, visit this link.

Happy coding!

Related posts:

An Absolute Beginner Guide to Node Package Manager
Uploading Files using Formidable in a Node.js Application
Writing A Multiplayer Text Adventure Engine In Node.js: Creating The Terminal Client (Part 3)
Multithreading trong Nodejs
Building A Room Detector For IoT Devices On Mac OS
How To Build and Test a Node.js REST API with Express on Ubuntu 18.04
Introduction to Express.js
Session Management in Node.js using ExpressJS and Express Session
Keeping Node.js Fast: Tools, Techniques, And Tips For Making High-Performance Node.js Servers
Debugging a Node.Js app using Chrome Dev Tools
How to Perform Custom Ranking for Records from a MongoDB Database in Node.js
Speakeasy Two-factor Authentication in Node.js
How to build a real time chat application in Node.js
Building A Node.js Express API To Convert Markdown To HTML
How to Create a Simple REST API using TypeScript and Node.js
Process Manager 2 with Node.js
Building your First Telegram Bot using Node.js and Telegraf
Creating Secure Password Flows With NodeJS And MySQL
How To Build A CLI Tool With Node.js And PhantomJS
Converting a Static Site to a Static Site Generator
Getting Started with Node.js REPL
Deploying RESTful APIs using Node.js, Express 4 to Kubernetes clusters
How to Prevent Cross-Site Scripting in Node.js
How to Generate Fake Data in Node.js Using Faker.js
Why Node.js is Good for Online Stores
How to Implement Caching using Adonis.js 5
Introduction to Job Scheduling in Node.js
How to Integrate B2C M-Pesa API using Node.js
Next Generation Server Compression With Brotli
Getting Started with Fastify Node.js Framework and Faunadb
Node.js Callback Concept
Top Node.js Interview Questions