-
Notifications
You must be signed in to change notification settings - Fork 30.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Doc: Adding guide on Timers #6825
Closed
Closed
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
1c0f9ad
Merge remote-tracking branch 'nodejs/master'
ryanmurakami c73869c
moving timer guide to core
ryanmurakami e419e50
Changing inline code blocks to single backticks
ryanmurakami 291d1aa
shortening code block syntax & shortening lines
ryanmurakami deec87d
standardizing Node.js spelling
ryanmurakami 5c16d99
changes based on feedback
ryanmurakami 5475e00
time
ryanmurakami 011a95e
rewriting usages of "you"
ryanmurakami 80ec978
Updating based on feedback
ryanmurakami 103e566
feedback changes
ryanmurakami 020b941
Merge remote-tracking branch 'nodejs/master'
ryanmurakami 20c55c0
grammar revisions in process.nextTick()
ryanmurakami 0fb1eeb
s-s-s-spaces
ryanmurakami 14a644f
Revising link to guide sentence
ryanmurakami 9377403
Merge branch 'master' of https://github.com/ryanmurakami/node
ryanmurakami 2f78f5f
rolling back whoops change
ryanmurakami f7fa1a9
feedback
ryanmurakami afa5167
Adding link to MDN docs for window.setTimeout()
ryanmurakami File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps...
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, sounds good. |
||
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) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted in the docs, you can also pass any number of arguments though to the function being called via
setTimeout()
, beyond the 2nd argument.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added explanation and revised the example to demo this as well.