mirror of https://github.com/lukechilds/node.git
Browse Source
Refs: https://github.com/nodejs/docs/issues/76 PR-URL: https://github.com/nodejs/node/pull/6825 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>v6.x
Ryan Lewis
9 years ago
committed by
Jeremiah Senkpiel
2 changed files with 214 additions and 22 deletions
@ -0,0 +1,192 @@ |
|||
--- |
|||
title: Timers in Node.js |
|||
layout: docs.hbs |
|||
--- |
|||
|
|||
# Timers in Node.js and beyond |
|||
|
|||
The Timers module in Node.js contains functions that execute code after a set |
|||
period of time. Timers do not need to be imported via `require()`, since |
|||
all the methods are available globally to emulate the browser JavaScript API. |
|||
To fully understand when timer functions will be executed, it's a good idea to |
|||
read up on the the Node.js |
|||
[Event Loop](../topics/the-event-loop-timers-and-nexttick). |
|||
|
|||
## Controlling the Time Continuum with Node.js |
|||
|
|||
The Node.js API provides several ways of scheduling code to execute at |
|||
some point after the present moment. The functions below may seem familiar, |
|||
since they are available in most browsers, but Node.js actually provides |
|||
its own implementation of these methods. Timers integrate very closely |
|||
with the system, and despite the fact that the API mirrors the browser |
|||
API, there are some differences in implementation. |
|||
|
|||
### "When I say so" Execution ~ *`setTimeout()`* |
|||
|
|||
`setTimeout()` can be used to schedule code execution after a designated |
|||
amount of milliseconds. This function is similar to |
|||
[`window.setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout) |
|||
from the browser JavaScript API, however a string of code cannot be passed |
|||
to be executed. |
|||
|
|||
`setTimeout()` accepts a function to execute as its first argument and the |
|||
millisecond delay defined as a number as the second argument. Additional |
|||
arguments may also be included and these will be passed on to the function. Here |
|||
is an example of that: |
|||
|
|||
```js |
|||
function myFunc (arg) { |
|||
console.log('arg was => ' + arg); |
|||
} |
|||
|
|||
setTimeout(myFunc, 1500, 'funky'); |
|||
``` |
|||
|
|||
The above function `myFunc()` will execute as close to 1500 |
|||
milliseconds (or 1.5 seconds) as possible due to the call of `setTimeout()`. |
|||
|
|||
The timeout interval that is set cannot be relied upon to execute after |
|||
that *exact* number of milliseconds. This is because other executing code that |
|||
blocks or holds onto the event loop will push the execution of the timeout |
|||
back. The *only* guarantee is that the timeout will not execute *sooner* than |
|||
the declared timeout interval. |
|||
|
|||
`setTimeout()` returns a `Timeout` object that can be used to reference the |
|||
timeout that was set. This returned object can be used to cancel the timeout ( |
|||
see `clearTimeout()` below) as well as change the execution behavior (see |
|||
`unref()` below). |
|||
|
|||
### "Right after this" Execution ~ *`setImmediate()`* |
|||
|
|||
`setImmediate()` will execute code at the end of the current event loop cycle. |
|||
This code will execute *after* any I/O operations in the current event loop and |
|||
*before* any timers scheduled for the next event loop. This code execution |
|||
could be thought of as happening "right after this", meaning any code following |
|||
the `setImmediate()` function call will execute before the `setImmediate()` |
|||
function argument. |
|||
|
|||
The first argument to `setImmediate()` will be the function to execute. Any |
|||
subsequent arguments will be passed to the function when it is executed. |
|||
Here's an example: |
|||
|
|||
```js |
|||
console.log('before immediate'); |
|||
|
|||
setImmediate((arg) => { |
|||
console.log(`executing immediate: ${arg}`); |
|||
}, 'so immediate'); |
|||
|
|||
console.log('after immediate'); |
|||
``` |
|||
|
|||
The above function passed to `setImmediate()` will execute after all runnable |
|||
code has executed, and the console output will be: |
|||
|
|||
```shell |
|||
before immediate |
|||
after immediate |
|||
executing immediate: so immediate |
|||
``` |
|||
|
|||
`setImmediate()` returns and `Immediate` object, which can be used to cancel |
|||
the scheduled immediate (see `clearImmediate()` below). |
|||
|
|||
Note: Don't get `setImmediate()` confused with `process.nextTick()`. There are |
|||
some major ways they differ. The first is that `process.nextTick()` will run |
|||
*before* any `Immediate`s that are set as well as before any scheduled I/O. |
|||
The second is that `process.nextTick()` is non-clearable, meaning once |
|||
code has been scheduled to execute with `process.nextTick()`, the execution |
|||
cannot be stopped, just like with a normal function. Refer to [this guide](../topics/the-event-loop-timers-and-nexttick#processnexttick) |
|||
to better understand the operation of `process.nextTick()`. |
|||
|
|||
### "Infinite Loop" Execution ~ *`setInterval()`* |
|||
|
|||
If there is a block of code that should execute multiple times, `setInterval()` |
|||
can be used to execute that code. `setInterval()` takes a function |
|||
argument that will run an infinite number of times with a given millisecond |
|||
delay as the second argument. Just like `setTimeout()`, additional arguments |
|||
can be added beyond the delay, and these will be passed on to the function call. |
|||
Also like `setTimeout()`, the delay cannot be guaranteed because of operations |
|||
that may hold on to the event loop, and therefore should be treated as an |
|||
approximate delay. See the below example: |
|||
|
|||
```js |
|||
function intervalFunc () { |
|||
console.log('Cant stop me now!'); |
|||
} |
|||
|
|||
setInterval(intervalFunc, 1500); |
|||
``` |
|||
In the above example, `intervalFunc()` will execute about every 1500 |
|||
milliseconds, or 1.5 seconds, until it is stopped (see below). |
|||
|
|||
Just like `setTimeout()`, `setInterval()` also returns a `Timeout` object which |
|||
can be used to reference and modify the interval that was set. |
|||
|
|||
## Clearing the Future |
|||
|
|||
What can be done if a `Timeout` or `Immediate` object needs to be cancelled? |
|||
`setTimeout()`, `setImmediate()`, and `setInterval()` return a timer object |
|||
that can be used to reference the set `Timeout` or `Immediate` object. |
|||
By passing said object into the respective `clear` function, execution of |
|||
that object will be halted completely. The respective functions are |
|||
`clearTimeout()`, `clearImmediate()`, and `clearInterval()`. See the example |
|||
below for an example of each: |
|||
|
|||
```js |
|||
let timeoutObj = setTimeout(() => { |
|||
console.log('timeout beyond time'); |
|||
}, 1500); |
|||
|
|||
let immediateObj = setImmediate(() => { |
|||
console.log('immediately executing immediate'); |
|||
}); |
|||
|
|||
let intervalObj = setInterval(() => { |
|||
console.log('interviewing the interval'); |
|||
}, 500); |
|||
|
|||
clearTimeout(timeoutObj); |
|||
clearImmediate(immediateObj); |
|||
clearInterval(intervalObj); |
|||
``` |
|||
|
|||
## Leaving Timeouts Behind |
|||
|
|||
Remember that `Timeout` objects are returned by `setTimeout` and `setInterval`. |
|||
The `Timeout` object provides two functions intended to augment `Timeout` |
|||
behavior with `unref()` and `ref()`. If there is a `Timeout` object scheduled |
|||
using a `set` function, `unref()` can be called on that object. This will change |
|||
the behavior slightly, and not call the `Timeout` object *if it is the last |
|||
code to execute*. The `Timeout` object will not keep the process alive, waiting |
|||
to execute. |
|||
|
|||
In similar fashion, a `Timeout` object that has had `unref()` called on it |
|||
can remove that behavior by calling `ref()` on that same `Timeout` object, |
|||
which will then ensure its execution. Be aware, however, that this does |
|||
not *exactly* restore the initial behavior for performance reasons. See |
|||
below for examples of both: |
|||
|
|||
```js |
|||
let timerObj = setTimeout(() => { |
|||
console.log('will i run?'); |
|||
}); |
|||
|
|||
// if left alone, this statement will keep the above |
|||
// timeout from running, since the timeout will be the only |
|||
// thing keeping the program from exiting |
|||
timerObj.unref(); |
|||
|
|||
// we can bring it back to life by calling ref() inside |
|||
// an immediate |
|||
setImmediate(() => { |
|||
timerObj.ref(); |
|||
}); |
|||
``` |
|||
## Further Down the Event Loop |
|||
|
|||
There's much more to the Event Loop and Timers than this guide |
|||
has covered. To learn more about the internals of the Node.js |
|||
Event Loop and how Timers operate during execution, check out |
|||
this Node.js guide: [The Node.js Event Loop, Timers, and |
|||
process.nextTick()](../topics/the-event-loop-timers-and-nexttick). |
Loading…
Reference in new issue