A useful feature of Node.js and JavaScript is the ability to delay execution of code for a period of time. This can be useful for cleanup or refresh work that you do not want to always be running. You can implement three types of timers in Node.js: the timeout, interval, and immediate timers. The following sections describe each of these and how to implement them in your code.
Timeout timers are used to delay work for a specific amount of time. When that time expires, the callback function is executed, and the timer goes away. You should use timeouts for work that needs to be performed only once.
You create timeout timers by using the setTimeout(callback, delayMilliSeconds, [args])
method built into Node.js. When you call setTimeout()
, the callback function is executed after delayMilliSeconds
has expired. For example, the following executes myFunc()
after a second:
setTimeout(myFunc, 1000);
The setTimeout()
function returns a timer object ID, and you can pass this ID to clearTimeout(timeoutId)
at any time before delayMilliSeconds
expires to cancel the timeout function. For example:
myTimeout = setTimeout(myFunc, 100000);
...
clearTimeout(myTimeout);
The code in Listing 4.1 implements a series of simple timeouts that call the simpleTimeout()
function, which outputs the number of milliseconds since the timeout was scheduled. Notice that it doesn’t matter in which order setTimeout()
is called. The results, shown in Figure 4.4, appear in the order in which the delay expires.
01 function simpleTimeout(consoleTimer){
02 console.timeEnd(consoleTimer);
03 }
04 console.time("twoSecond");
05 setTimeout(simpleTimeout, 2000, "twoSecond");
06 console.time("oneSecond");
07 setTimeout(simpleTimeout, 1000, "oneSecond");
08 console.time("fiveSecond");
09 setTimeout(simpleTimeout, 5000, "fiveSecond");
10 console.time("50MilliSecond");
11 setTimeout(simpleTimeout, 50, "50MilliSecond");
Interval timers are used to perform work on a regular delayed interval. When the delay time expires, the callback function is executed and is then rescheduled for the delay interval again. You should use intervals for work that needs to be performed on a regular basis.
You create interval timers by using the setInterval(callback, delayMilliSeconds, [args])
method that is built into Node.js. When you call setInterval()
, the callback function is executed every interval after delayMilliSeconds
has expired. For example, the following executes myFunc()
every second:
setInterval(myFunc, 1000);
The setInterval()
function returns a timer object ID, and you can pass this ID to clearInterval(intervalId)
at any time before delayMilliSeconds
expires to cancel the timeout function. For example:
myInterval = setInterval(myFunc, 100000);
...
clearInterval(myInterval);
The code in Listing 4.2 implements a series of simple interval callbacks that update the values of the variables x
, y
, and z
at different intervals. Notice that the values of x
, y
, and z
are changed differently because the interval amounts are different; x
increments twice as fast as y
, which increments twice as fast as z
, as shown in the output in Figure 4.5.
01 var x=0, y=0, z=0;
02 function displayValues(){
03 console.log("X=%d; Y=%d; Z=%d", x, y, z);
04 }
05 function updateX(){
06 x += 1;
07 }
08 function updateY(){
09 y += 1;
10 }
11 function updateZ(){
12 z += 1;
13 displayValues();
14 }
15 setInterval(updateX, 500);
16 setInterval(updateY, 1000);
17 setInterval(updateZ, 2000);
Immediate timers are used to perform work as soon as the I/O event callbacks begin executing but before any timeout or interval events are executed. They allow you to schedule work to be done after the current events in the event queue are completed. You should use immediate timers to yield long-running execution segments to other callbacks to prevent starving the I/O events.
You create immediate timers by using the setImmediate(callback,[args])
method that is built into Node.js. When you call setImmediate()
, the callback function is placed on the event queue and popped off once for each iteration through the event queue loop after I/O events have a chance to be called. For example, the following code schedules myFunc()
to execute on the next cycle through the event queue:
setImmediate(myFunc(), 1000);
The setImmediate()
function returns a timer object ID, and you can pass this ID to clearImmediate(immediateId)
at any time before it is picked up from the event queue. For example:
myImmediate = setImmediate(myFunc);
...
clearImmediate(myImmediate);
Often you will not want timer event callbacks to continue to be scheduled when they are the only events left in the event queue. Node.js provides a very useful utility to handle this case. The unref()
function, available in the object returned by setInterval
and setTimeout
, allows you to notify the event loop to not continue when these are the only events on the queue.
For example, the following code dereferences the myInterval
interval timer:
myInterval = setInterval(myFunc);
myInterval.unref();
If for some reason you later do not want the program to terminate if the interval function is the only event left on the queue, you can use the ref()
function to re-reference it:
myInterval.ref();
Warning
When using unref()
with setTimout
timers, a separate timer is used to wake up the event loop. Using a lot of these can have an adverse performance impact on your code, so you should create them sparingly.