Understanding Node.js Child Processes

Node.js Logo

Since Node.js is single-threaded, CPU-intensive tasks can block the event loop and hurt performance. The `child_process` module allows you to spin up new processes to run these tasks in parallel, keeping your main application responsive.

When to Use Child Processes

  • For CPU-bound tasks like image processing, heavy calculations, or running external scripts.
  • To execute shell commands and interact with the operating system.

The `exec` Function

The `exec` function is useful for running shell commands. It buffers the command's output and passes it to a callback function once the process is complete. It's best for commands that return small amounts of data.

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

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

The `spawn` Function

The `spawn` function is more suitable for long-running processes or commands that return large amounts of data. It streams the data back as it's generated, which is much more memory-efficient than `exec`'s buffering.

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

const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

The `fork` Function

The `fork` function is a special case of `spawn` specifically for creating new Node.js processes. The key advantage is that it allows for communication between the parent and child processes via a built-in messaging channel.

Note: For scaling a web server across multiple CPU cores, the `cluster` module is often a better choice as it's specifically designed for that purpose.

Comments