Skip to content

Commit 45f83e5

Browse files
ryanmurakamiFishrock123
authored andcommitted
doc: add guide for Node.js Timers
Refs: nodejs/docs#76 PR-URL: #6825 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
1 parent b383fdd commit 45f83e5

File tree

2 files changed

+214
-22
lines changed

2 files changed

+214
-22
lines changed

doc/guides/timers-in-node.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
---
2+
title: Timers in Node.js
3+
layout: docs.hbs
4+
---
5+
6+
# Timers in Node.js and beyond
7+
8+
The Timers module in Node.js contains functions that execute code after a set
9+
period of time. Timers do not need to be imported via `require()`, since
10+
all the methods are available globally to emulate the browser JavaScript API.
11+
To fully understand when timer functions will be executed, it's a good idea to
12+
read up on the the Node.js
13+
[Event Loop](../topics/the-event-loop-timers-and-nexttick).
14+
15+
## Controlling the Time Continuum with Node.js
16+
17+
The Node.js API provides several ways of scheduling code to execute at
18+
some point after the present moment. The functions below may seem familiar,
19+
since they are available in most browsers, but Node.js actually provides
20+
its own implementation of these methods. Timers integrate very closely
21+
with the system, and despite the fact that the API mirrors the browser
22+
API, there are some differences in implementation.
23+
24+
### "When I say so" Execution ~ *`setTimeout()`*
25+
26+
`setTimeout()` can be used to schedule code execution after a designated
27+
amount of milliseconds. This function is similar to
28+
[`window.setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout)
29+
from the browser JavaScript API, however a string of code cannot be passed
30+
to be executed.
31+
32+
`setTimeout()` accepts a function to execute as its first argument and the
33+
millisecond delay defined as a number as the second argument. Additional
34+
arguments may also be included and these will be passed on to the function. Here
35+
is an example of that:
36+
37+
```js
38+
function myFunc (arg) {
39+
console.log('arg was => ' + arg);
40+
}
41+
42+
setTimeout(myFunc, 1500, 'funky');
43+
```
44+
45+
The above function `myFunc()` will execute as close to 1500
46+
milliseconds (or 1.5 seconds) as possible due to the call of `setTimeout()`.
47+
48+
The timeout interval that is set cannot be relied upon to execute after
49+
that *exact* number of milliseconds. This is because other executing code that
50+
blocks or holds onto the event loop will push the execution of the timeout
51+
back. The *only* guarantee is that the timeout will not execute *sooner* than
52+
the declared timeout interval.
53+
54+
`setTimeout()` returns a `Timeout` object that can be used to reference the
55+
timeout that was set. This returned object can be used to cancel the timeout (
56+
see `clearTimeout()` below) as well as change the execution behavior (see
57+
`unref()` below).
58+
59+
### "Right after this" Execution ~ *`setImmediate()`*
60+
61+
`setImmediate()` will execute code at the end of the current event loop cycle.
62+
This code will execute *after* any I/O operations in the current event loop and
63+
*before* any timers scheduled for the next event loop. This code execution
64+
could be thought of as happening "right after this", meaning any code following
65+
the `setImmediate()` function call will execute before the `setImmediate()`
66+
function argument.
67+
68+
The first argument to `setImmediate()` will be the function to execute. Any
69+
subsequent arguments will be passed to the function when it is executed.
70+
Here's an example:
71+
72+
```js
73+
console.log('before immediate');
74+
75+
setImmediate((arg) => {
76+
console.log(`executing immediate: ${arg}`);
77+
}, 'so immediate');
78+
79+
console.log('after immediate');
80+
```
81+
82+
The above function passed to `setImmediate()` will execute after all runnable
83+
code has executed, and the console output will be:
84+
85+
```shell
86+
before immediate
87+
after immediate
88+
executing immediate: so immediate
89+
```
90+
91+
`setImmediate()` returns and `Immediate` object, which can be used to cancel
92+
the scheduled immediate (see `clearImmediate()` below).
93+
94+
Note: Don't get `setImmediate()` confused with `process.nextTick()`. There are
95+
some major ways they differ. The first is that `process.nextTick()` will run
96+
*before* any `Immediate`s that are set as well as before any scheduled I/O.
97+
The second is that `process.nextTick()` is non-clearable, meaning once
98+
code has been scheduled to execute with `process.nextTick()`, the execution
99+
cannot be stopped, just like with a normal function. Refer to [this guide](../topics/the-event-loop-timers-and-nexttick#processnexttick)
100+
to better understand the operation of `process.nextTick()`.
101+
102+
### "Infinite Loop" Execution ~ *`setInterval()`*
103+
104+
If there is a block of code that should execute multiple times, `setInterval()`
105+
can be used to execute that code. `setInterval()` takes a function
106+
argument that will run an infinite number of times with a given millisecond
107+
delay as the second argument. Just like `setTimeout()`, additional arguments
108+
can be added beyond the delay, and these will be passed on to the function call.
109+
Also like `setTimeout()`, the delay cannot be guaranteed because of operations
110+
that may hold on to the event loop, and therefore should be treated as an
111+
approximate delay. See the below example:
112+
113+
```js
114+
function intervalFunc () {
115+
console.log('Cant stop me now!');
116+
}
117+
118+
setInterval(intervalFunc, 1500);
119+
```
120+
In the above example, `intervalFunc()` will execute about every 1500
121+
milliseconds, or 1.5 seconds, until it is stopped (see below).
122+
123+
Just like `setTimeout()`, `setInterval()` also returns a `Timeout` object which
124+
can be used to reference and modify the interval that was set.
125+
126+
## Clearing the Future
127+
128+
What can be done if a `Timeout` or `Immediate` object needs to be cancelled?
129+
`setTimeout()`, `setImmediate()`, and `setInterval()` return a timer object
130+
that can be used to reference the set `Timeout` or `Immediate` object.
131+
By passing said object into the respective `clear` function, execution of
132+
that object will be halted completely. The respective functions are
133+
`clearTimeout()`, `clearImmediate()`, and `clearInterval()`. See the example
134+
below for an example of each:
135+
136+
```js
137+
let timeoutObj = setTimeout(() => {
138+
console.log('timeout beyond time');
139+
}, 1500);
140+
141+
let immediateObj = setImmediate(() => {
142+
console.log('immediately executing immediate');
143+
});
144+
145+
let intervalObj = setInterval(() => {
146+
console.log('interviewing the interval');
147+
}, 500);
148+
149+
clearTimeout(timeoutObj);
150+
clearImmediate(immediateObj);
151+
clearInterval(intervalObj);
152+
```
153+
154+
## Leaving Timeouts Behind
155+
156+
Remember that `Timeout` objects are returned by `setTimeout` and `setInterval`.
157+
The `Timeout` object provides two functions intended to augment `Timeout`
158+
behavior with `unref()` and `ref()`. If there is a `Timeout` object scheduled
159+
using a `set` function, `unref()` can be called on that object. This will change
160+
the behavior slightly, and not call the `Timeout` object *if it is the last
161+
code to execute*. The `Timeout` object will not keep the process alive, waiting
162+
to execute.
163+
164+
In similar fashion, a `Timeout` object that has had `unref()` called on it
165+
can remove that behavior by calling `ref()` on that same `Timeout` object,
166+
which will then ensure its execution. Be aware, however, that this does
167+
not *exactly* restore the initial behavior for performance reasons. See
168+
below for examples of both:
169+
170+
```js
171+
let timerObj = setTimeout(() => {
172+
console.log('will i run?');
173+
});
174+
175+
// if left alone, this statement will keep the above
176+
// timeout from running, since the timeout will be the only
177+
// thing keeping the program from exiting
178+
timerObj.unref();
179+
180+
// we can bring it back to life by calling ref() inside
181+
// an immediate
182+
setImmediate(() => {
183+
timerObj.ref();
184+
});
185+
```
186+
## Further Down the Event Loop
187+
188+
There's much more to the Event Loop and Timers than this guide
189+
has covered. To learn more about the internals of the Node.js
190+
Event Loop and how Timers operate during execution, check out
191+
this Node.js guide: [The Node.js Event Loop, Timers, and
192+
process.nextTick()](../topics/the-event-loop-timers-and-nexttick).

doc/topics/the-event-loop-timers-and-nexttick.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
The event loop is what allows Node.js to perform non-blocking I/O
66
operations — despite the fact that JavaScript is single-threaded — by
7-
offloading operations to the system kernel whenever possible.
7+
offloading operations to the system kernel whenever possible.
88

99
Since most modern kernels are multi-threaded, they can handle multiple
1010
operations executing in the background. When one of these operations
1111
completes, the kernel tells Node.js so that the appropriate callback
1212
may added to the `poll` queue to eventually be executed. We'll explain
1313
this in further detail later in this topic.
1414

15-
## Event Loop Explained
15+
## Event Loop Explained
1616

1717
When Node.js starts, it initializes the event loop, processes the
1818
provided input script (or drops into the REPL, which is not covered in
@@ -67,7 +67,7 @@ actually uses are those above._
6767

6868
## Phases Overview:
6969

70-
* `timers`: this phase executes callbacks scheduled by `setTimeout()`
70+
* `timers`: this phase executes callbacks scheduled by `setTimeout()`
7171
and `setInterval()`.
7272
* `I/O callbacks`: most types of callback except timers, setImmedate, close
7373
* `idle, prepare`: only used internally
@@ -88,22 +88,22 @@ _may be executed_ rather than the **exact** time a person _wants it to
8888
be executed_. Timers callbacks will run as early as they can be
8989
scheduled after the specified amount of time has passed; however,
9090
Operating System scheduling or the running of other callbacks may delay
91-
them.
91+
them.
9292

93-
_**Note**: Technically, the [`poll` phase](#poll) controls when timers
93+
_**Note**: Technically, the [`poll` phase](#poll) controls when timers
9494
are executed._
9595

96-
For example, say you schedule a timeout to execute after a 100 ms
97-
threshold, then your script starts asynchronously reading a file which
96+
For example, say you schedule a timeout to execute after a 100 ms
97+
threshold, then your script starts asynchronously reading a file which
9898
takes 95 ms:
9999

100100
```js
101101

102102
var fs = require('fs');
103103

104104
function someAsyncOperation (callback) {
105-
106-
// let's assume this takes 95ms to complete
105+
106+
// let's assume this takes 95ms to complete
107107
fs.readFile('/path/to/file', callback);
108108

109109
}
@@ -149,12 +149,12 @@ more events.
149149

150150
### I/O callbacks:
151151

152-
This phase executes callbacks for some system operations such as types
152+
This phase executes callbacks for some system operations such as types
153153
of TCP errors. For example if a TCP socket receives `ECONNREFUSED` when
154154
attempting to connect, some \*nix systems want to wait to report the
155155
error. This will be queued to execute in the `I/O callbacks` phase.
156156

157-
### poll:
157+
### poll:
158158

159159
The poll phase has two main functions:
160160

@@ -171,7 +171,7 @@ either the queue has been exhausted, or the system-dependent hard limit
171171
is reached.
172172

173173
* _If the `poll` queue **is empty**_, one of two more things will
174-
happen:
174+
happen:
175175
* If scripts have been scheduled by `setImmediate()`, the event loop
176176
will end the `poll` phase and continue to the `check` phase to
177177
execute those scheduled scripts.
@@ -202,7 +202,7 @@ etc. However, after a callback has been scheduled with `setImmediate()`,
202202
then the `poll` phase becomes idle, it will end and continue to the
203203
`check` phase rather than waiting for `poll` events.
204204

205-
### `close callbacks`:
205+
### `close callbacks`:
206206

207207
If a socket or handle is closed abruptly (e.g. `socket.destroy()`), the
208208
`'close'` event will be emitted in this phase. Otherwise it will be
@@ -211,10 +211,10 @@ emitted via `process.nextTick()`.
211211
## `setImmediate()` vs `setTimeout()`
212212

213213
`setImmediate` and `setTimeout()` are similar, but behave in different
214-
ways depending on when they are called.
214+
ways depending on when they are called.
215215

216216
* `setImmediate()` is designed to execute a script once the current
217-
`poll` phase completes.
217+
`poll` phase completes.
218218
* `setTimeout()` schedules a script to be run
219219
after a minimum threshold in ms has elapsed.
220220

@@ -379,7 +379,7 @@ We have two calls that are similar as far as users are concerned, but
379379
their names are confusing.
380380

381381
* `process.nextTick()` fires immediately on the same phase
382-
* `setImmediate()` fires on the following iteration or 'tick' of the
382+
* `setImmediate()` fires on the following iteration or 'tick' of the
383383
event loop
384384

385385
In essence, the names should be swapped. `process.nextTick()` fires more
@@ -393,7 +393,7 @@ While they are confusing, the names themselves won't change.
393393
easier to reason about (and it leads to code that's compatible with a
394394
wider variety of environments, like browser JS.)*
395395

396-
## Why use `process.nextTick()`?
396+
## Why use `process.nextTick()`?
397397

398398
There are two main reasons:
399399

@@ -420,7 +420,7 @@ the event loop to proceed it must hit the `poll` phase, which means
420420
there is a non-zero chance that a connection could have been received
421421
allowing the connection event to be fired before the listening event.
422422

423-
Another example is running a function constructor that was to, say,
423+
Another example is running a function constructor that was to, say,
424424
inherit from `EventEmitter` and it wanted to call an event within the
425425
constructor:
426426

@@ -440,10 +440,10 @@ myEmitter.on('event', function() {
440440
});
441441
```
442442

443-
You can't emit an event from the constructor immediately
444-
because the script will not have processed to the point where the user
445-
assigns a callback to that event. So, within the constructor itself,
446-
you can use `process.nextTick()` to set a callback to emit the event
443+
You can't emit an event from the constructor immediately
444+
because the script will not have processed to the point where the user
445+
assigns a callback to that event. So, within the constructor itself,
446+
you can use `process.nextTick()` to set a callback to emit the event
447447
after the constructor has finished, which provides the expected results:
448448

449449
```js

0 commit comments

Comments
 (0)