On his drive home from school, George encounters an all knowing Genie whose car has broken down. Knowing a thing or two about cars, he stops to help.
George: Hey, it looks like you're having some car trouble?
Genie: It's my battery. The thing's completely dead. I've been stuck here for an hour and nobody's stopped.
George: Well most people don't know enough about cars to help. I used to work as a mechanic before I decided to go back to school.
Genie: Yes, you're studying computer science.
George: (begins to turn pale, and backs away slowly)
Genie: Sorry! I forgot to mention, I'm an all knowing genie.
George: You could have led with that...
Genie: Look, if you help me jump my battery I'll grant you one wish. The only thing you can't ask for is world peace.
George: I wish someone would explain how Node.js works. We're using it in one of my classes and it seems pretty powerful and user-friendly. It's so easy to start using that I never really stopped to learn what it's doing behind the scenes.
Genie: Seriously? You could have wished for money, fame, love.
George: "The pursuit of knowledge is more valuable than it's possession. Albert Ein—"
Genie: I know who said it. Remember? All knowing genie over here.
Genie: Ok, before I explain how Node.js works, tell me in a nutshell what you already know about it.
George: I know it's a programming language, like Python or Javascript. Actually, it's not just "like" Javascript. It sort of "is" Javascript? I know Javascript runs in the browser to make websites interactive, and Node.js is like a server side version of Javascript you can use to build web applications.
Genie: Not bad, I can work with that. Let's build on what you already know and then we'll go deeper into how Node.js works behind the scenes.
Genie: First, a small correction. Node.js is not actually a programming language, though that's a common misconception. It's a cross-platform runtime environment for Javascript. By cross-platform I mean it can run on Linux, Windows, OSX, and many others. You were right in that it's a way to run a Javascript program outside of the browser, i.e. on a server.
Genie: Second, a bit of history. It's not enough to just know how Node.js works. You also need to know why it became so popular. To put things in perspective, in 2020 Node.js was downloaded over 100 million times. Why do you think Node.js become so popular?
George: Because web developers need to switch technologies every five years or they turn to stone?
Genie: Very funny. No, one of the main reasons Node.js, or "Node" as it's sometimes called , became so popular is that everyone already knew how to use it. I know that sounds like a contradiction, but think about it this way—by the time Node.js arrived, most web developers already knew how to program in Javascript. If one already knew Javascript, building a web application using Node.js just required knowing general server-side development concepts. Widespread adoption happened very fast.
George: But if I'm a web developer in 2010 and I've used Php and Apache for my previous five projects, why would I switch to Node.js just because I happen to know Javascript? There has to be something else that made it such a compelling alternative.
Genie: You understand this better than I gave you credit for. There is something else that makes Node.js special compared to Php. When your teacher introduced Node.js, how did they describe it?
George: They referred to it as "asynchronous" and "event-driven" but we didn't go too deep into what that actually means.
Genie: Ok, good. We'll come back to those two terms in a moment. Remember that with Php and Apache, each incoming request to a web application creates a new process. Imagine a connection to a Php web application that's requesting a record from the database and an image file. Other requests to the web application will be blocked while the those two requests are fulfilled. A traditional Php/Apache application is not asynchronous. Computers are fast though, and this generally isn't a problem if you're only dealing with a few hundred simultaneous connections. But what if 5,000 people visit you website at the same time? Processes each get a chunk of memory and they don't share it. A rush of visitors to your site could cause your web server to run out of memory and stop it from responding to requests.
George: I'm guessing Node.js is not one process per request.
Genie: It is not. In fact, all your Javascript in a Node.js application is executed in a single thread. The reason Node.js can do this is because it uses non-blocking (asynchronous) I/O and an event loop. What this means is that unlike your Php application, when a request arives asking for a database record and an image file, Node.js registers a callback function that will run when that data is ready and then immediately moves on to the next incoming request. Those I/O operations are added to a queue and are processed by the Node.js event loop which delegates I/O tasks to non-blocking C++ APIs. When that database record and image file are ready, the callback function fires and the requested data is sent to the client that requested it. Have I thoroughly confused you yet?
George: No, I mostly understand what you're saying. Php launches a new process for each request, which have to be processes synchronously. NodeJS handles all requests in the same process and uses non-blocking system calls to accomplish asynchronous execution.
Genie: That's a good way of summarizing it. One thing I forgot to mention is that nowadays there are web servers and libraries one can use with Php to accomplish event-based non-blocking I/O with performance similar to what Node.js offers. At the time Node.js came out though, the relative performance gains were real.
George: Tell me more about this "event loop" that allows Node.js to run all the program code in a single thread.
Genie: I'm glad you asked, the event loop is the magic that makes Node.js special. You know how it's the operating system's job to schedule the order in which tasks will run on a computer? The event loop is like a scheduler for the thread that a Node.js program runs on. It has a number of phases it loops through that determine the order in which program tasks will execute. For example, one phase of the event loop is dedicated to checking whether various OS system calls running on other threads have completed, i.e. getting the contents of a file.
George: So Node.js will quickly delegate I/O tasks to be done asynchronously on other threads, and meanwhile is constantly checking via the event loop when those tasks are done at which point it can fire the callback function registered to that task.
Genie: George, I couldn't have said it better myself. Now, help me jump my battery.
George: We should have done that first. Your battery could have been charging while you were teaching me how Node.js works.