Asynchronous event-driven architecture allows Node.js to perform non-blocking operations, which is a fundamental aspect of its efficiency. However, there are scenarios where this non-blocking paradigm needs a helping hand to manage CPU-intensive tasks. This is where the child_process module of Node.js comes into play, offering the capability to spawn child processes for better resource management and application scalability. In this detailed guide, we explore the child_process module with real examples and scenarios to showcase its powerful capabilities.
Understanding the child_process module
The child_process module in Node.js is a built-in module that allows you to execute other applications or scripts in your environment. This module enables you to run processes in your system as a child of your Node.js process. It provides various functions to spawn new processes, pipe input/output (IO), and handle asynchronous events.
Main advantages of using child_process
Non-Blocking Operations: By offloading tasks to child processes, you can keep the main event loop free from heavy computation, ensuring your application remains responsive.
Utilize Multi-core Systems: It enables Node.js applications to take advantage of multi-core systems, running parallel processes.
Diverse Execution Environment: With the ability to run shell commands, you can execute scripts written in different languages, not just JavaScript, widening the capability of your Node.js application.
Isolated Computation: Child processes run in their own V8 instances, which provides memory isolation and prevents crashes in the child process from directly affecting the parent process.
Example 1: Spawning a child process
We will create a simple child process that executes a command to list files in the current directory (ls -lh
on UNIX-based systems or dir
on Windows).
Create a file named listFiles.js
:
const { spawn } = require('child_process');
// Platform check to set the correct command
const command = process.platform === 'win32' ? 'dir' : 'ls';
const args = process.platform === 'win32' ? [] : ['-lh'];
const child = spawn(command, args);
child.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
child.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
child.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
This script will output the list of files and directories in the current location where the script is run.
Example 2: Communicating with a child process via IPC
Inter-process communication (IPC) allows bidirectional communication between the parent and child processes.
Create a file named child.js:
process.on('message', (msg) => {
console.log('Message from parent:', msg);
process.send({ childData: 'Hello from child process' });
});
Create a file named parent.js:
const { fork } = require('child_process');
const child = fork('./child.js');
child.on('message', (msg) => {
console.log('Message from child:', msg);
});
child.send({ parentData: 'Hello from parent process' });
This example will demonstrate two-way communication between the parent and child process.
Scenarios where child_process can be used
Background Processing: Tasks such as generating reports or processing large files can be done in the background without blocking the main thread.
Microservices: Spawn child processes for different microservices to communicate over IPC or through a messaging system.
Script Execution: Use child_process
to run shell scripts or utilities directly from your Node.js code.
Complex Calculations: Perform heavy calculations in a separate process to prevent blocking the event loop.