Skip to content

Commit 1e90e68

Browse files
authored
fix: update event loop timers and nexttick page (#23)
Signed-off-by: Viacheslav Muravyev <slavamuravey@mail.ru>
1 parent 775888e commit 1e90e68

File tree

1 file changed

+74
-68
lines changed

1 file changed

+74
-68
lines changed

pages/asynchronous-work/event-loop-timers-and-nexttick.md

Lines changed: 74 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ order of operations.
2424

2525
```
2626
┌───────────────────────────┐
27-
┌─>│ timers │
28-
│ └─────────────┬─────────────┘
29-
│ ┌─────────────┴─────────────┐
30-
│ │ pending callbacks │
27+
│ timers │
28+
└─────────────┬─────────────┘
29+
30+
v
31+
┌───────────────────────────┐
32+
┌─>│ pending callbacks │
3133
│ └─────────────┬─────────────┘
3234
│ ┌─────────────┴─────────────┐
3335
│ │ idle, prepare │
@@ -39,7 +41,10 @@ order of operations.
3941
│ │ check │
4042
│ └─────────────┬─────────────┘
4143
│ ┌─────────────┴─────────────┐
42-
└──┤ close callbacks │
44+
│ │ close callbacks │
45+
│ └─────────────┬─────────────┘
46+
│ ┌─────────────┴─────────────┐
47+
└──┤ timers │
4348
└───────────────────────────┘
4449
```
4550

@@ -68,16 +73,17 @@ longer than a timer's threshold. See the [**timers**](#timers) and
6873
6974
## Phases Overview
7075

71-
- **timers**: this phase executes callbacks scheduled by `setTimeout()`
72-
and `setInterval()`.
7376
- **pending callbacks**: executes I/O callbacks deferred to the next loop
7477
iteration.
7578
- **idle, prepare**: only used internally.
7679
- **poll**: retrieve new I/O events; execute I/O related callbacks (almost
7780
all with the exception of close callbacks, the ones scheduled by timers,
7881
and `setImmediate()`); node will block here when appropriate.
7982
- **check**: `setImmediate()` callbacks are invoked here.
80-
- **close callbacks**: some close callbacks, e.g. `socket.on('close', ...)`.
83+
- **close callbacks**: some close callbacks, e.g. `socket.on('close', ...)`
84+
- **timers**: this phase executes callbacks scheduled by `setTimeout()`
85+
and `setInterval()`. Additionally, these callbacks can execute before entering the event loop.
86+
This sometimes happens for setTimeout(() => { ... }, 0) outside the I/O loop.
8187

8288
Between each run of the event loop, Node.js checks if it is waiting for
8389
any asynchronous I/O or timers and shuts down cleanly if there are not
@@ -90,6 +96,66 @@ and how they interact with timers in certain scenarios.
9096

9197
## Phases in Detail
9298

99+
### pending callbacks
100+
101+
This phase executes callbacks for some system operations such as types
102+
of TCP errors. For example if a TCP socket receives `ECONNREFUSED` when
103+
attempting to connect, some \*nix systems want to wait to report the
104+
error. This will be queued to execute in the **pending callbacks** phase.
105+
106+
### poll
107+
108+
The **poll** phase has two main functions:
109+
110+
1. Calculating how long it should block and poll for I/O, then
111+
2. Processing events in the **poll** queue.
112+
113+
When the event loop enters the **poll** phase _and there are no timers
114+
scheduled_, one of two things will happen:
115+
116+
- _If the **poll** queue **is not empty**_, the event loop will iterate
117+
through its queue of callbacks executing them synchronously until
118+
either the queue has been exhausted, or the system-dependent hard limit
119+
is reached.
120+
121+
- _If the **poll** queue **is empty**_, one of two more things will
122+
happen:
123+
- If scripts have been scheduled by `setImmediate()`, the event loop
124+
will end the **poll** phase and continue to the **check** phase to
125+
execute those scheduled scripts.
126+
127+
- If scripts **have not** been scheduled by `setImmediate()`, the
128+
event loop will wait for callbacks to be added to the queue, then
129+
execute them immediately.
130+
131+
Once the **poll** queue is empty the event loop will check for timers
132+
_whose time thresholds have been reached_. If one or more timers are
133+
ready, the event loop will wrap back to the **timers** phase to execute
134+
those timers' callbacks.
135+
136+
### check
137+
138+
This phase allows the event loop to execute callbacks immediately after the
139+
**poll** phase has completed. If the **poll** phase becomes idle and
140+
scripts have been queued with `setImmediate()`, the event loop may
141+
continue to the **check** phase rather than waiting.
142+
143+
`setImmediate()` is actually a special timer that runs in a separate
144+
phase of the event loop. It uses a libuv API that schedules callbacks to
145+
execute after the **poll** phase has completed.
146+
147+
Generally, as the code is executed, the event loop will eventually hit
148+
the **poll** phase where it will wait for an incoming connection, request,
149+
etc. However, if a callback has been scheduled with `setImmediate()`
150+
and the **poll** phase becomes idle, it will end and continue to the
151+
**check** phase rather than waiting for **poll** events.
152+
153+
### close callbacks
154+
155+
If a socket or handle is closed abruptly (e.g. `socket.destroy()`), the
156+
`'close'` event will be emitted in this phase. Otherwise it will be
157+
emitted via `process.nextTick()`.
158+
93159
### timers
94160

95161
A timer specifies the **threshold** _after which_ a provided callback
@@ -177,66 +243,6 @@ be 105ms.
177243
> also has a hard maximum (system dependent) before it stops polling for
178244
> more events.
179245
180-
### pending callbacks
181-
182-
This phase executes callbacks for some system operations such as types
183-
of TCP errors. For example if a TCP socket receives `ECONNREFUSED` when
184-
attempting to connect, some \*nix systems want to wait to report the
185-
error. This will be queued to execute in the **pending callbacks** phase.
186-
187-
### poll
188-
189-
The **poll** phase has two main functions:
190-
191-
1. Calculating how long it should block and poll for I/O, then
192-
2. Processing events in the **poll** queue.
193-
194-
When the event loop enters the **poll** phase _and there are no timers
195-
scheduled_, one of two things will happen:
196-
197-
- _If the **poll** queue **is not empty**_, the event loop will iterate
198-
through its queue of callbacks executing them synchronously until
199-
either the queue has been exhausted, or the system-dependent hard limit
200-
is reached.
201-
202-
- _If the **poll** queue **is empty**_, one of two more things will
203-
happen:
204-
- If scripts have been scheduled by `setImmediate()`, the event loop
205-
will end the **poll** phase and continue to the **check** phase to
206-
execute those scheduled scripts.
207-
208-
- If scripts **have not** been scheduled by `setImmediate()`, the
209-
event loop will wait for callbacks to be added to the queue, then
210-
execute them immediately.
211-
212-
Once the **poll** queue is empty the event loop will check for timers
213-
_whose time thresholds have been reached_. If one or more timers are
214-
ready, the event loop will wrap back to the **timers** phase to execute
215-
those timers' callbacks.
216-
217-
### check
218-
219-
This phase allows the event loop to execute callbacks immediately after the
220-
**poll** phase has completed. If the **poll** phase becomes idle and
221-
scripts have been queued with `setImmediate()`, the event loop may
222-
continue to the **check** phase rather than waiting.
223-
224-
`setImmediate()` is actually a special timer that runs in a separate
225-
phase of the event loop. It uses a libuv API that schedules callbacks to
226-
execute after the **poll** phase has completed.
227-
228-
Generally, as the code is executed, the event loop will eventually hit
229-
the **poll** phase where it will wait for an incoming connection, request,
230-
etc. However, if a callback has been scheduled with `setImmediate()`
231-
and the **poll** phase becomes idle, it will end and continue to the
232-
**check** phase rather than waiting for **poll** events.
233-
234-
### close callbacks
235-
236-
If a socket or handle is closed abruptly (e.g. `socket.destroy()`), the
237-
`'close'` event will be emitted in this phase. Otherwise it will be
238-
emitted via `process.nextTick()`.
239-
240246
## `setImmediate()` vs `setTimeout()`
241247

242248
`setImmediate()` and `setTimeout()` are similar, but behave in different

0 commit comments

Comments
 (0)