16. Node.js Lessons. Event Loop, libUV Library. Part 2


On that joyful note JavaScript execution ends, and libUV checks whether there is any watcher that can be activated, which means whether there is any internal handler. If there is no handler, the whole Node.js process gets finished, as well as the whole event loop, too. In our case, one watcher of this kind, in particular a port 3000 handler, was installed. That’s why a Node.js process is not going to finish, but will get a stand-by mode. It will stay in this mode until some reason to get activated occurs – for example, new input-output events.

Sooner or later a similar event is likely to happen. An operational system signal will occur notifying that someone got connected to the port 3000; an internal libUV watcher will send a callback, which will deliver this signal to libUV and it will get to Node.js. The Node.js wrapping will immediately generate the connection event and will start to analyze what is being sent to us. Later, if the data analysis shows it is an http-request, the request event will be generated and this handler will finally get activated:

Whether the url is like that:

the handler reading gets initiated using libUV.

We send a command to libUV, while JavaScript finishes its work at the current point. That’s all – your request event is handled. Provided the fact JavaScript has ended its execution and there are internal libUV handlers, the process doesn’t get terminated and acquires a stand-by mode. Certain events can end this mode. But what events?

The first one is a new request, while the second one is a file reading completion or any error occurred; but all these are of little importance for us at the moment. Whenever something happens, the respective JavaScript callback will be initiated.

As we can see, our JavaScript code plays the leading role. It tells libUV: initiate this or that process – for example, a file reading – or get connection at that certain port. LibUV can correctly transmit this information to our operational system. Next, the OS initiates various activities, while libUV is waiting for its response. Whenever the OS responds, libUV calls our JavaScript code again for it to find a solution and maybe initiate some new input-output process. Afterwards, the process gets a stand-by mode again. And this loop is every time the same.

Everything seems pretty much clear. In fact, there are some other aspects. For example, imagine that the first event here is a receiving of a new request. Control gets delivered to JavaScript, and suddenly at the moment of its execution the file reading gets ended, internal libUV handlers get activated, but at this moment JavaScript is busy! That’s why an internal libUV event stands in a line. It turns out that while JavaScript is busy with some activity, libUV can get a whole line of events waiting to be handled. Whenever JavaScript gets its work finished, it turns to this event line, takes the first event out of it and starts its handling. The process gets repeated every time.

Handling of internal libUV events will be sequential. For example, if we handle John’s request and reading of Merry, Peter and Elon’s files has just ended, which means 3 new internal events, these events have formed a line and will be sequentially handled by a JavaScript interpreter.

However, despite of the fact there is only one line for events, you will see no hassle because whenever a respective callback is initiated, it gets all information about this request from JavaScript closure. It means, if callback for Ylon has launched, there will be req for Peter. If callback has launched for Merry, it will be a different function and closure, respectively. The handling will continue and Merry will receive a response.

On the other hand, it turns out that in order to provide effective server functioning JavaScript needs to be executed extremely fast, which means no new event waiting for its turn. What will happen, if JavaScript gets slow? For example, if there is some hard computing task and Node.js is busy, the events get stacked. This situation is called Event Loop Starvation. Thus, handling of all clients depending on it will get slow, too, and it is not good at all. In order to avoid this heavy computing problem, the task gets included into a separate process or independent flow or the Node.js server gets launched in a multiprocessing mode. For example, you can do it by using a built-in cluster module, but that isn’t the only solution. Another variant is to divide a hard computing task into parts – for example, one part of an answer can be generated into functions

Later, using setTimeOut 10 ms you can postpone generation of the second part’s response, etc. So, you will have the same volume of the executed work, but JavaScript will be divided into parts in the process. During these computing gaps the server can do something else by handling other clients. However, all these solutions add some complexity, that’s why Node.js is used primarily in the situations that do not require complicated computing or data sharing. The practice shows, the greatest part of these tasks is connected with web development.

So, let us conclude.

  • Library libUV is a heart of Node.js. It is both a benefit and a downside of Node.js.
  • From one hand, libUV enables to do multiple input/output operations simultaneously, which means our JavaScript code can initiate an operation and continue doing its work. As a result, a number of input/output operations can be simultaneously handled by the OS, while JavaScript will send data from one client to another, from a database to a client, etc. Seamlessly and effectively.
  • From the other hand, all these require asynchronous development. Not readFileSync, but readFile. The callback system common for Node.js is rather simple, but at the same time more complicated than average sequential commands of synchronous development. Moreover, since the JavaScript process must handle a lot of events, it is highly recommended not to make it wait, but give it an opportunity to do everything quickly in order not to create a long line of events. This  Node.js feature needs to be considered from the very beginning, when you start your web app development. You may wonder whether there can be any complex computing operations that may block JavaScript. Well, for example, parsing of a big json or md5sum computing for a heavy downloaded file.

These tasks influence the server productivity a way earlier the moment our working JavaScript devour 100% of our processor. It means, Node.js can eat 20%, but work not that effectively just because when JavaScript is busy, other tasks that even require different resources (database, for example) cannot continue the work. In order to protect themselves from such situations, developers usually launch Node.js apps in a multi-processor mode.

It will be even more interesting next time. Stay tuned!

You can find lesson’s  code following this link

Materials has taken from following screencast

We are looking forward to meeting you on our website soshace.com

About the author

Stay Informed

It's important to keep up
with industry - subscribe!

Stay Informed

Looks good!
Please enter the correct name.
Please enter the correct email.
Looks good!

Related articles


How To Use Prospector For Python Static Code Analysis

Prospector is a tool that analyzes Python code, outputs information about the errors, potential problems, convention violation, and complexity of the ...


Fluent Validation in ASP.NET MVC

Fluent validation is a validation library for .NET. This will be separated from the business logic. So, it has an advantage over data annotation ...

How to implement WPF Canvas? Explain with an example

Canvas is a lightweight layout of WPF. Canvas is used for 2D graphic design elements but not for UI. You cannot use it for making text-box, checkbox, ...

No comments yet

Sign in

Forgot password?

Or use a social network account


By Signing In \ Signing Up, you agree to our privacy policy

Password recovery

You can also try to

Or use a social network account


By Signing In \ Signing Up, you agree to our privacy policy