Chapter 2: Why Node.js? Advantages vs RPG, Java, Python and PHP
Node.js "Event Loops" smell like the old RPG Logic Cycle
If you've written RPGLE for any length of time, you think in a nice straight line: READ, do stuff, UPDATE, READ again, DOW NOT %EOF. One job, one thing at a time, top to bottom. Lovely.
If you're coming from Legacy RPG (System 36 Cycle Code), think of the Node.js event loop as a modern version of the RPG logic cycle. In classic RPG, the logic cycle repeatedly reads a record, processes it, and decides what to do next, all behind the scenes. Node.js does something similar, but instead of cycling through database records, its event loop continuously watches for events such as web requests, API calls, file reads, or user actions. When something needs attention, Node.js hands it off to the appropriate code and then immediately goes back to listening for the next event. Both models are designed to keep work flowing efficiently, but while the RPG logic cycle is built around record processing, the Node.js event loop is built around handling asynchronous events in a modern, connected world.
Node.js does things a little differently, and if you understand this one idea the rest of the course will be a doddle.
Single thread, non-blocking
Node.js runs your JavaScript on one thread. "One thread?!" I hear you cry. "My interactive subsystem has 400 jobs!" Stay with me.
The trick is that Node.js never waits. When you ask it to do something slow - read a file, run an SQL statement, call a web service - it hands that work off and carries on with the next thing. When the slow work finishes, a callback gets queued, and the event loop picks it up and runs it.
Think of a waiter in a restaurant. A "blocking" waiter takes your order, walks to the kitchen, and stands there until your steak is cooked. A Node.js waiter takes your order, gives it to the kitchen, then goes and takes ten more orders while the steak sizzles.
Seeing it in code
console.log('1. Order taken');
setTimeout(() => {
console.log('3. Steak is ready (after 1 second)');
}, 1000);
console.log('2. Taking the next order...');
Run it with node eventloop.js and you get:
2. Taking the next order...
3. Steak is ready (after 1 second)
async / await - the bit that makes it readable again
Modern JavaScript gives us async and await, which let you write non-blocking code that reads like nice top-down RPG:
const fs = require('fs/promises');
async function main() {
const text = await fs.readFile('/etc/motd', 'utf8'); // waits without blocking the loop
console.log(text);
}
main().catch(err => console.error('Oops:', err.message));
We'll use async/await everywhere in this course, especially for our database calls. Just remember: await only works inside an async function, and always handle errors (that .catch() is not optional decoration).
The one gotcha
Because it's one thread, a CPU-heavy loop (say, calculating pi to a billion places) will block everybody else. Node.js shines at I/O-heavy work - web APIs, database calls, gluing systems together - which, coincidentally, is exactly what we want to bolt onto the IBM i.
