The Node.js Event Loop

The Node.js event loop is one of the most confusing parts about learning how to craft a well designed server in Node.

The first thing you need to understand is that Node.js is a single threaded process. This means that it can only handle one task at a time. Sounds super great for a system that is supposed to serve a website or API to multiple people at once, right?

Well, this is where the event loop comes in. Think of it as a first-in-first-out task queue, or FIFO Queue. A FIFO queue means that every new task goes to the back of the line, and waits its turn to be executed, just like when you go to the grocery store and have to wait in line.

It kinda looks like this:
event loop

I'm sure that looks confusing, but before we talk about the individual parts of that image let's first talk about callbacks, which are one of the most unique characteristics of JavaScript.

Callbacks can be either anonymous or named functions that handle the response from another function. Let's consider this function, foo:

const foo = (url) => {
    $http.get(url);
}

foo is a function that takes a URL as an argument, and makes a GET request to that URL. You might use a function like foo when you want to make a GET request quite often, but don't want to repeat the code for the request every time. The only problem with foo right now is that you have no way to get the data it returns. It diligently sends off your GET request, but you don't know if it succeeded or failed.

This is where callbacks and the event loop come in to play.

Let's go back to the grocery store analogy real quick. You're stuck behind a guy, lets call him Bob. You can't cut Bob in line, because he was there before you and that's not how waiting in line works. When it's Bob's turn to be checked out, he realized that he forgot the ice cream that he promised his wife. Obviously can't go home without that, right? So he leaves all of his stuff at the register and goes to get the ice cream, leaving you stranded while you wait for Bob and his ice cream. Bob is now what we call a blocker.

Remember how Node.js servers can only process one task at a time? Grocery store checkouts are the same way. Imagine for a second though that Bob's cart got put to the side with all of his stuff still in it, and you were able to check out while Bob runs to grab the ice cream. When Bob comes back with his ice cream, he gets back in line and finishes checking out when it is his turn again.

That's what the event loop does for you. When a blocking task gets fired, it gets put to the side while everything else continues executing. When the blocking task is done, it calls back and says "Hey, I'm ready to work again!"

Let's modify our function foo from before a little bit. We're going to make it do something after the GET request finishes.

const success = (data) => {
    console.log(data);
}

const foo = (url) => {
    $http.get(url, success);
}

See that success function we added? That's a callback that we are passing to $http.get. I'm sure that looks confusing, but it's actually pretty straight forward. What's happening is that the $http.get function is firing off the GET request which could take a long time - we don't know exactly how long it will take. What we are doing here though is telling $http.get to tell us when it is done by calling success and passing success the data that it gets back from the url.

This is just like the grocery store checkout. Instead of forcing all of the other code to wait before executing, the $http.get function simply tells us when it has what we want, and then we can continue from there instead of blocking everything!

Now that we have talked about FIFO queues, callbacks, and single threaded processes, let's take a look at the picture from before again, specifically the right half of it:
event loop

I bet it makes a bit more sense now. The event queue is the grocery store line, where each function (person) is waiting to be processed (checked out). If there is something that would be a blocker, like Bob and his ice cream or someone else's server that needs to respond to you, it gets back in line when it is done instead of holding everything up.

This is what makes Node such a quick framework. Instead of getting stuck waiting for a database or cache or whatever to respond, Node will keep processing other peoples requests and will come back to yours when you are done.

Hopefully this has helped you understand the Node Event Loop a little bit more, and understand why nearly everything in Node has a callback. You don't want to be stuck waiting in line for Bob to get his ice cream. You want Bob to get back in line when he comes back with his ice cream.