SIGN IN

17. Node.js Lessons. Timers, Differences from Browser, ref and ref

Stay Informed

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

Stay Informed

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

timeout

Hey, guys! Our today’s article will tell you about Node.js timers. Here we will try to tell you about all the differences existing between browser and Node.js timers. So, let us refer to our technical materials and see a number of similar methods:

Timers

  • setTimeout(callback, delay, [arg], […])
  • clearTimeout(timeoutId)
  • setInterval(callback, delay, [arg], […])
  • clearInterval(intervalId)

Your work will be pretty much the same both in Node.js and browser. The differences will be seen later. The first one will be analyzed using an example of a server of this kind:

As you can see, the server is very simple here. We can say, it is an abstract http server listening to Port 3000 and making something with queries. At some point, for example, in 2.5 seconds we decide to stop the server functioning. By calling server.close();  the server stops acquiring new connections, but as long as there are any received and unclosed queries, they will be still handled. And whenever all connections are handled and closed, the process will finish. In our case, I launch the process, and if there is no query, the process gets ended in 2.5 sec. Everything is quite clear and expected so far.

And now let us imagine that working with the server I want to receive information on a console memory usage. Well, it is not a big deal. We output a special query procces.memoryUsage every second:

I launch our current server. Have a look. Info, info… Is the server running? Yes, it is. But what is the reason? Why didn’t a process end, when over 2.5 sec. have passed? Of course the reason is these strings:

As far as we remember, libUV library is responsible for timers and input/output events. LibUV cannot finish the process, until there is an active timer. So, what should we do? Let us analyze several solutions. The first one is to do a callback in a close function that will work, whenever the server handles and closes all connections. Write process.exit there:

So, let us try. It works! From one hand, it is ok, but on the other – rather severe, reminding rough interjection of a process. Do it a little softer when cleaning your timer:

It looks ok, but this variant is not perfect from the architectural point either. Think a little. Here is a server:

It may be in one file, while this SetInterval can be included into another module:

Moreover, there can be the third module that holds its own server or does its own operations. Let us pretend what will happen, if right here:

we will do an “exit”.

In this case, the whole process will die, including those operations servers never touch, if there are any of them. Bad! Now the message output will simply stop, while other operations will still be executed. It is a bit better, but not ideal, anyway.

In fact, the right solution will be to use specialized Node.js abilities. In particular, let us use this special method called timer.unref:

As we can see, compared to browser JavaScript, here timer is an object, and timer.unref method informs libUV that this timer is secondary. It means, you do not need to count it when controlling internal watchers ending the process. Let us launch it. As soon as the server ends its work and there is no other internal watcher, except for the unref timer, the process will end.

There is another ref method. It is opposite to the unref one. It means, if I do timer.unref and then take this idea back, I can call a ref method. It is rarely used in practice.
So, why is this solution better? Just because here a timer indicates it is not necessary, which we actually need. No side-effect is registered.
Note, this unref method is familiar not only to timers. Servers or network sockets also have it. It means, I can do a network connection that won’t be an obstacle for the process end being unimportant for some reason.

Further in our technical materials we see setImmediate(), setInterval() methods different from the browser ones. To understand it better, let us analyze an example below. We’ve got a web server, and its query handling function needs to complete some operation asynchronously.

The browser generally uses either setTimeout 0, or setImmediate query and its emulation with various hacks for that case. But remember that a browser has a different event loop, and browser’s setImmediate is quite different, too. We won’t talk about it now. Let us see, what’s going on with setTimeout 0 in Node. When will this code trigger? Can we guarantee its completion before another query comes? Of course, we can’t. setTimeout will execute it very soon, but when exactly – it is still unclear. It can happen before another query or even later. However, there are situations, when we need to know exactly that some asynchronous code is to be executed before Node receives another query or any other input-output event. For example, we’ve got a request, and, within this setTimeout, we want to hang a handler for the following data:
We need to know exactly this handler will be hanged before other data are read. To solve this task, Node.js has a special call – process.nextTick. From the one side, will do the function execution asynchronous, which means it will be completed only after completing the current JavaScript, while from the other side, it guarantees its execution before next input-output, timer or other events come. Moreover, when handling this function, process.nextTick, you see some other events to be asynchronously planned, nested recursive calls process.nextTick will also add their function completion right here, too. Thus, we can hang handlers 100% guarantee, and they will work before other data come.

There may occur another situation, when we want to make a function asynchronous, but do not slow down the event loop. Our next example is when we’ve got a big computing task, but in order not to block JavaScript here for a long period, we can try to divide it into parts. One will be launched right here, while the other is to be launched in a way it works upon the next loop iteration, the third one – upon the next, etc. To do so, Node.js has a call setImmediate. It plans function execution in a way for it to operate, from the one side, as soon as possible, and at the loop’s next iteration upon current events handling, from the other side.

Let us see the differences between nextTick and setImmediate pictured by this example:

Here we use a fs module to open a file. Its opening here is quite simple – as an input-output operation. Whenever a file is open, the inner libUV event will trigger causing this function. Next, using setImmediate and nextTick plan message output. Let us see in what order they will be displayed. What do you thing? Launch it.

Well, the first one is nextTick, of course, because it is planned upon the current JavaScript ending, but before any input-output event, which means a file opening in fact. setImmediate was executed following Input-Output because that’s the way it has planned its execution. And what would happen, if we added setTimeout 0 here? What would happen? No one knows.

So, we’ve analyzed how Node.js timers differ from the browser ones.

  • First, there is a certain influence on the process completion and ref/unref
  • Second, the difference is in various setTimeout 0 forms:nextTick and setImmediate. nextTick is commonly used. It guarantees the event completion prior to new events – in particular, new input-output operations and new data. Generally, it is the most secure variant.
  • setImmediate plans execution for the next loop iteration, following the event handling. In general, we need this solutions whenever we do not really care about event handling, which means we want to do something asynchronously and we do not want to slow down the even loop in this case; or whenever we divide a complex task into parts to handle one part right now, and leave others for the next loop iteration, respectively. Thus, we see that the task is being slowly executed by giving some other events and clients be completed in between its parts. And there will be no serious pause in servicing.

The lesson code can be found in our repository

software-computer-code-1940x900_35196

The article materials were borrowed from the 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 correct name
Please enter correct email
Looks good!

Related articles

The Path of the Self-Taught Programmer: Avoiding Common Problems

In this article, we’ll explore how a self-taught programmer comes to be: which education opportunities they can utilize, which problems they may>>>

Programming

Introduction to GitHub Desktop: A GUI Enhancement to a CLI Approach

In this article, we'll explore various use cases of GitHub Desktop -- GUI software designed to ehance your git workflow. Does it hold up against CLI>>>

Programming
29.10.2019

Python Array Explained and Visualized

In this tutorial, we’ll delve into how Python arrays work, what their limitations are, and how you can use them to maximize their>>>

Programming

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