Node.js - forking guide and example in NodeJS/express

Published on

You can use fork to spawn child processes, that can run in the background.

If you have a regular express app, and it has to call a function that uses a lot of resources, it can block all other requests coming in

(You could also use something like pm2 to get around this).

In this example, I'm going to calculate the fibonacci number in a very slow way. But maybe in the real world you are running an expensive calculation and it would block other requests.

note: await-ing a db call or other IO is not blocking in the same way, and has minimal impact on speed. The issue is what JS itself is doing lots of blocking calculation.

There are 2 parts - the main server, and a file ("module") that gets forked.

You send messages two ways between them.

An example should explain more:

server.js
const express = require('express')
const {fork} = require('child_process')

const app = express()

app.get('/fibonacci/:num', (req, res) => {
    // when we get a new request come in...
    
    console.log(`server.js: received request for ${req.params.num}`)
    
    // create a child forked process:
    const child = fork('./child.js')
    
    // send a message to the child - in this case the number from URL
    child.send(Number(req.params.num))
    
    // when this (parent) receives a msg (from child), we can send it to the
    // response's res.send()
    child.on('message', fib => {
        console.log('server.js: received message with Fibonacci result');
        res.send(`The ${req.params.num}th Fibonacci number is ${fib}`)
    })
})


app.listen(3322)
console.log("Now visit these urls, and they're not blocked");
console.log("http://localhost:3322/fibonacci/20");
console.log("http://localhost:3322/fibonacci/30");
console.log("http://localhost:3322/fibonacci/100");
child.js
// slow function...
const fibonacci = n => {
    // slow way to calculate fib, to demonstrate forking
    if (n < 2) return n
    return fibonacci(n - 1) + fibonacci(n - 2)
}

// receive an emitted event from the parent:
process.on('message', num => {
    console.log(`child.js: received message of ${num}`)
    const result = fibonacci(num); // this is very slow! it would normally block...
    
    // send it back to the parent:
    process.send(result)
})