Back

May 3, 2021

A Node.js introduction you really need

An important introduction to building backend applications with the JavaScript runtime, using Node.js.

nodejsbackenddevelopment

Sometimes it's quite hard to learn a programming language, mostly because we don't know where to start. Let's go!

Node.js is nothing more than JavaScript running on the server, and that's a very good thing for many reasons. But before you start coding, it's important to understand some key concepts and a bit of history.

It's also very important to understand that Node.js is not a magic solution, and it isn't always the best solution for every project or problem. Anyone can start a server in Node.js, but writing scalable web applications requires a deeper understanding of the language.

Before Node.js

Pull up a chair — here comes the story...

Most web applications were written in a server/client model, where the client requests a resource from the server, which in turn responds with the requested resources. That way, the server only responds when the client asks, and closes the connection after each response.

This pattern is efficient, since each request to the server consumes time and resources (CPU, memory, network, etc.). So it makes more sense to close the connection after the server responds to the request, so that it can also respond to the next ones.

So, thinking about this architecture, how does a server respond to hundreds or thousands of requests at the same time? Well, that's what something called threads is for. Threads, in short, are a way for systems to run multiple operations simultaneously. Therefore, each request opens a new thread, and each thread has everything it needs to execute an operation until its completion.

This thread system has a disadvantage (or more...): the time will come when there are too many requests, and the increase in child threads will end up consuming a large amount of resources (memory, CPU, etc.). This can cause requests to slow down. Since each new request is handled by a new thread, the main thread has to work very efficiently, making the system faster and able to serve requests more quickly.

All of this is quite efficient because each operation runs code outside the main thread. But things can always be better, can't they?

Enter Node.js

Imagine a multi-threaded server running Ruby on Rails — the previous version of my site was in Ruby :). In it there is an operation to read a file stored on the server and respond to the request with the data. Ruby, in turn, doesn't read files directly; it relies on the file system to perform that operation. So the request is made to the file system, and meanwhile Ruby keeps a thread waiting for its response, only returning the answer to whoever made the request afterward.

This is where Node.js steps in with all its wisdom. Using the same example above, while the file system is reading the file, Node.js uses the idle time to handle other requests. When the file system finishes, it will notify Node.js to fetch the information and return it as the response to the request. This is possible because of the well-known event loop.

The event loop is basically a program that waits for events and dispatches them when they happen. An important fact to mention here is that JavaScript is single-threaded, and therefore so is Node.js.

Unlike other languages that require a new thread for each request, Node.js takes all the requests and delegates most of the work to other workers in the system. As soon as those background workers finish their work, they emit the callback events registered for it.

Another important item: callbacks! They are basically functions passed to other functions as arguments, and they are called when certain conditions occur.

So what Node.js programmers basically do is write event handlers.

But is Node.js faster than other multi-threaded systems? Yes, even being single-threaded.

It's also very important to know that everything in JavaScript runs in parallel — except your code. Yes, your code runs one thing at a time, even when other workers are doing their work simultaneously. Hang on, let's draw an analogy in case you haven't understood 100% of it.

Imagine the president of the republic has an aide. The president writes a list of things they want done and sends it to their aide, who in turn delegates the work to several other employees. When they finish, the aide brings the results to the president. The president is always busy writing other lists while the aide and the employees are working.

In this analogy, the president is your code. Even though many things are running in parallel, it does one thing at a time. Your employees are Node.js's workers. "Everything runs in parallel, except your code" – Mikito Takada.

Conclusion

Whew! I think this got a bit long, so let's stop here for this first article.

If you want to write scalable applications with Node.js, you need to know more than just writing code and routing with express. It's important to understand how it works, behind the code. The next steps will be getting to know concepts such as synchronous/asynchronous, promises, callbacks, and others. But let's take it one step at a time! ;)

Still have questions? Did you like the analogies? Drop a comment and let's chat!