@@ -9,15 +9,15 @@ offloading operations to the system kernel whenever possible.
9
9
Since most modern kernels are multi-threaded, they can handle multiple
10
10
operations executing in the background. When one of these operations
11
11
completes, the kernel tells Node.js so that the appropriate callback
12
- may added to the ` poll ` queue to eventually be executed. We'll explain
12
+ may added to the ** poll** queue to eventually be executed. We'll explain
13
13
this in further detail later in this topic.
14
14
15
15
## Event Loop Explained
16
16
17
17
When Node.js starts, it initializes the event loop, processes the
18
18
provided input script (or drops into the REPL, which is not covered in
19
19
this document) which may make async API calls, schedule timers, or call
20
- ` process.nextTick() ` , then begins processing the event loop.
20
+ ` process.nextTick() ` , then begins processing the event loop.
21
21
22
22
The following diagram shows a simplified overview of the event loop's
23
23
order of operations.
@@ -47,36 +47,36 @@ Each phase has a FIFO queue of callbacks to execute. While each phase is
47
47
special in its own way, generally, when the event loop enters a given
48
48
phase, it will perform any operations specific to that phase, then
49
49
execute callbacks in that phase's queue until the queue has been
50
- exhausted or the maximum number of callbacks have executed. When the
50
+ exhausted or the maximum number of callbacks has executed. When the
51
51
queue has been exhausted or the callback limit is reached, the event
52
52
loop will move to the next phase, and so on.
53
53
54
54
Since any of these operations may schedule _ more_ operations and new
55
- events processed in the ` poll ` phase are queued by the kernel, poll
55
+ events processed in the ** poll** phase are queued by the kernel, poll
56
56
events can be queued while polling events are being processed. As a
57
57
result, long running callbacks can allow the poll phase to run much
58
- longer than a timer's threshold. See the [ ` timers ` ] ( #timers ) and
59
- [ ` poll ` ] ( #poll ) sections for more details.
58
+ longer than a timer's threshold. See the [ ** timers** ] ( #timers ) and
59
+ [ ** poll** ] ( #poll ) sections for more details.
60
60
61
61
_ ** NOTE:** There is a slight discrepancy between the Windows and the
62
62
Unix/Linux implementation, but that's not important for this
63
63
demonstration. The most important parts are here. There are actually
64
64
seven or eight steps, but the ones we care about — ones that Node.js
65
- actually uses are those above._
65
+ actually uses - are those above._
66
66
67
67
68
- ## Phases Overview:
68
+ ## Phases Overview
69
69
70
- * ` timers ` : this phase executes callbacks scheduled by ` setTimeout() `
70
+ * ** timers** : this phase executes callbacks scheduled by ` setTimeout() `
71
71
and ` setInterval() ` .
72
- * ` I/O callbacks ` : most types of callback except timers, setImmedate, close
73
- * ` idle, prepare ` : only used internally
74
- * ` poll ` : retrieve new I/O events; node will block here when appropriate
75
- * ` check ` : setImmediate callbacks are invoked here
76
- * ` close callbacks ` : e.g socket.on('close', ...)
72
+ * ** I/O callbacks** : most types of callback except timers, ` setImmedate() ` , close
73
+ * ** idle, prepare** : only used internally
74
+ * ** poll** : retrieve new I/O events; node will block here when appropriate
75
+ * ** check** : ` setImmediate() ` callbacks are invoked here
76
+ * ** close callbacks** : e.g socket.on('close', ...)
77
77
78
78
Between each run of the event loop, Node.js checks if it is waiting for
79
- any asynchronous I/O or timer and it shuts down cleanly if there are not
79
+ any asynchronous I/O or timers and shuts down cleanly if there are not
80
80
any.
81
81
82
82
## Phases in Detail
@@ -90,7 +90,7 @@ scheduled after the specified amount of time has passed; however,
90
90
Operating System scheduling or the running of other callbacks may delay
91
91
them.
92
92
93
- _ ** Note** : Technically, the [ ` poll ` phase] ( #poll ) controls when timers
93
+ _ ** Note** : Technically, the [ ** poll** phase] ( #poll ) controls when timers
94
94
are executed._
95
95
96
96
For example, say you schedule a timeout to execute after a 100 ms
@@ -102,10 +102,8 @@ takes 95 ms:
102
102
var fs = require (' fs' );
103
103
104
104
function someAsyncOperation (callback ) {
105
-
106
- // let's assume this takes 95ms to complete
105
+ // Assume this takes 95ms to complete
107
106
fs .readFile (' /path/to/file' , callback);
108
-
109
107
}
110
108
111
109
var timeoutScheduled = Date .now ();
@@ -131,78 +129,77 @@ someAsyncOperation(function () {
131
129
});
132
130
```
133
131
134
- When the event loop enters the ` poll ` phase, it has an empty queue
135
- (` fs.readFile() ` has not completed) so it will wait for the number of ms
132
+ When the event loop enters the ** poll** phase, it has an empty queue
133
+ (` fs.readFile() ` has not completed), so it will wait for the number of ms
136
134
remaining until the soonest timer's threshold is reached. While it is
137
135
waiting 95 ms pass, ` fs.readFile() ` finishes reading the file and its
138
- callback which takes 10 ms to complete is added to the ` poll ` queue and
136
+ callback which takes 10 ms to complete is added to the ** poll** queue and
139
137
executed. When the callback finishes, there are no more callbacks in the
140
138
queue, so the event loop will see that the threshold of the soonest
141
- timer has been reached then wrap back to the ` timers ` phase to execute
139
+ timer has been reached then wrap back to the ** timers** phase to execute
142
140
the timer's callback. In this example, you will see that the total delay
143
- between the timer being scheduled and its callback being executed will
141
+ between the timer being scheduled and its callback being executed will
144
142
be 105ms.
145
143
146
- Note: To prevent the ` poll ` phase from starving the event loop, libuv
147
- also has a hard maximum (system dependent) before it stops ` poll ` ing for
144
+ Note: To prevent the ** poll** phase from starving the event loop, libuv
145
+ also has a hard maximum (system dependent) before it stops polling for
148
146
more events.
149
147
150
- ### I/O callbacks:
148
+ ### I/O callbacks
151
149
152
150
This phase executes callbacks for some system operations such as types
153
151
of TCP errors. For example if a TCP socket receives ` ECONNREFUSED ` when
154
152
attempting to connect, some \* nix systems want to wait to report the
155
- error. This will be queued to execute in the ` I/O callbacks ` phase.
156
-
157
- ### poll:
153
+ error. This will be queued to execute in the ** I/O callbacks** phase.
158
154
159
- The poll phase has two main functions:
155
+ ### poll
160
156
161
- 1 . Executing scripts for timers who's threshold has elapsed, then
162
- 2 . Processing events in the ` poll ` queue.
157
+ The ** poll** phase has two main functions:
163
158
159
+ 1 . Executing scripts for timers whose threshold has elapsed, then
160
+ 2 . Processing events in the ** poll** queue.
164
161
165
- When the event loop enters the ` poll ` phase _ and there are no timers
162
+ When the event loop enters the ** poll** phase _ and there are no timers
166
163
scheduled_ , one of two things will happen:
167
164
168
- * _ If the ` poll ` queue ** is not empty** _ , the event loop will iterate
169
- through its queue of callbacks executing them synchronously until
170
- either the queue has been exhausted, or the system-dependent hard limit
165
+ * _ If the ** poll** queue ** is not empty** _ , the event loop will iterate
166
+ through its queue of callbacks executing them synchronously until
167
+ either the queue has been exhausted, or the system-dependent hard limit
171
168
is reached.
172
169
173
- * _ If the ` poll ` queue ** is empty** _ , one of two more things will
170
+ * _ If the ** poll** queue ** is empty** _ , one of two more things will
174
171
happen:
175
172
* If scripts have been scheduled by ` setImmediate() ` , the event loop
176
- will end the ` poll ` phase and continue to the ` check ` phase to
173
+ will end the ** poll** phase and continue to the ** check** phase to
177
174
execute those scheduled scripts.
178
175
179
176
* If scripts ** have not** been scheduled by ` setImmediate() ` , the
180
177
event loop will wait for callbacks to be added to the queue, then
181
- execute it immediately.
178
+ execute them immediately.
182
179
183
- Once the ` poll ` queue is empty the event loop will check for timers
180
+ Once the ** poll** queue is empty the event loop will check for timers
184
181
_ whose time thresholds have been reached_ . If one or more timers are
185
- ready, the event loop will wrap back to the timers phase to execute
182
+ ready, the event loop will wrap back to the ** timers** phase to execute
186
183
those timers' callbacks.
187
184
188
- ### ` check ` :
185
+ ### check
189
186
190
- This phase allows a person to execute callbacks immediately after the
191
- ` poll ` phase has completed. If the ` poll ` phase becomes idle and
192
- scripts have been queued with ` setImmediate() ` , the event loop may
193
- continue to the ` check ` phase rather than waiting.
187
+ This phase allows a person to execute callbacks immediately after the
188
+ ** poll** phase has completed. If the ** poll** phase becomes idle and
189
+ scripts have been queued with ` setImmediate() ` , the event loop may
190
+ continue to the ** check** phase rather than waiting.
194
191
195
192
` setImmediate() ` is actually a special timer that runs in a separate
196
193
phase of the event loop. It uses a libuv API that schedules callbacks to
197
- execute after the ` poll ` phase has completed.
194
+ execute after the ** poll** phase has completed.
198
195
199
196
Generally, as the code is executed, the event loop will eventually hit
200
- the ` poll ` phase where it will wait for an incoming connection, request,
201
- etc. However, after a callback has been scheduled with ` setImmediate() ` ,
202
- then the ` poll ` phase becomes idle, it will end and continue to the
203
- ` check ` phase rather than waiting for ` poll ` events.
197
+ the ** poll** phase where it will wait for an incoming connection, request,
198
+ etc. However, if a callback has been scheduled with ` setImmediate() `
199
+ and the ** poll** phase becomes idle, it will end and continue to the
200
+ ** check** phase rather than waiting for ** poll** events.
204
201
205
- ### ` close callbacks ` :
202
+ ### close callbacks
206
203
207
204
If a socket or handle is closed abruptly (e.g. ` socket.destroy() ` ), the
208
205
` 'close' ` event will be emitted in this phase. Otherwise it will be
@@ -214,12 +211,12 @@ emitted via `process.nextTick()`.
214
211
ways depending on when they are called.
215
212
216
213
* ` setImmediate() ` is designed to execute a script once the current
217
- ` poll ` phase completes.
218
- * ` setTimeout() ` schedules a script to be run
219
- after a minimum threshold in ms has elapsed.
214
+ ** poll** phase completes.
215
+ * ` setTimeout() ` schedules a script to be run after a minimum threshold
216
+ in ms has elapsed.
220
217
221
218
The order in which the timers are executed will vary depending on the
222
- context in which they are called. If both are called from within the
219
+ context in which they are called. If both are called from within the
223
220
main module, then timing will be bound by the performance of the process
224
221
(which can be impacted by other applications running on the machine).
225
222
@@ -248,7 +245,6 @@ setImmediate(function immediate () {
248
245
immediate
249
246
timeout
250
247
251
-
252
248
However, if you move the two calls within an I/O cycle, the immediate
253
249
callback is always executed first:
254
250
@@ -278,22 +274,22 @@ The main advantage to using `setImmediate()` over `setTimeout()` is
278
274
` setImmediate() ` will always be executed before any timers if scheduled
279
275
within an I/O cycle, independently of how many timers are present.
280
276
281
- ## ` process.nextTick() ` :
277
+ ## ` process.nextTick() `
282
278
283
279
### Understanding ` process.nextTick() `
284
280
285
281
You may have noticed that ` process.nextTick() ` was not displayed in the
286
- diagram, even though its a part of the asynchronous API. This is because
282
+ diagram, even though it's a part of the asynchronous API. This is because
287
283
` process.nextTick() ` is not technically part of the event loop. Instead,
288
- the nextTickQueue will be processed after the current operation
289
- completes, regardless of the current ` phase ` of the event loop.
284
+ the ` nextTickQueue ` will be processed after the current operation
285
+ completes, regardless of the current phase of the event loop.
290
286
291
287
Looking back at our diagram, any time you call ` process.nextTick() ` in a
292
288
given phase, all callbacks passed to ` process.nextTick() ` will be
293
289
resolved before the event loop continues. This can create some bad
294
290
situations because ** it allows you to "starve" your I/O by making
295
- recursive ` process.nextTick() ` calls. ** which prevents the event loop
296
- from reaching the ` poll ` phase.
291
+ recursive ` process.nextTick() ` calls** , which prevents the event loop
292
+ from reaching the ** poll** phase.
297
293
298
294
### Why would that be allowed?
299
295
@@ -319,9 +315,9 @@ What we're doing is passing an error back to the user but only *after*
319
315
we have allowed the rest of the user's code to execute. By using
320
316
` process.nextTick() ` we guarantee that ` apiCall() ` always runs its
321
317
callback * after* the rest of the user's code and * before* the event loop
322
- is allowed to proceed. To acheive this, the JS call stack is allowed to
318
+ is allowed to proceed. To achieve this, the JS call stack is allowed to
323
319
unwind then immediately execute the provided callback which allows a
324
- person to make recursive calls to nextTick without reaching a
320
+ person to make recursive calls to ` process. nextTick() ` without reaching a
325
321
` RangeError: Maximum call stack size exceeded from v8 ` .
326
322
327
323
This philosophy can lead to some potentially problematic situations.
@@ -343,21 +339,33 @@ var bar = 1;
343
339
```
344
340
345
341
The user defines ` someAsyncApiCall() ` to have an asynchronous signature,
346
- actually operates synchronously. When it is called, the callback
347
- provided to ` someAsyncApiCall () ` is called in the same phase of the
342
+ but it actually operates synchronously. When it is called, the callback
343
+ provided to ` someAsyncApiCall() ` is called in the same phase of the
348
344
event loop because ` someAsyncApiCall() ` doesn't actually do anything
349
- asynchronously. As a result, the callback tries to reference ` bar ` but
350
- it may not have that variable in scope yet because the script has not
345
+ asynchronously. As a result, the callback tries to reference ` bar ` even
346
+ though it may not have that variable in scope yet, because the script has not
351
347
been able to run to completion.
352
348
353
- By placing it in a ` process.nextTick() ` , the script still has the
349
+ By placing the callback in a ` process.nextTick() ` , the script still has the
354
350
ability to run to completion, allowing all the variables, functions,
355
- etc., to be initialized prior to the callback being called. It also has
351
+ etc., to be initialized prior to the callback being called. It also has
356
352
the advantage of not allowing the event loop to continue. It may be
357
- useful that the user be alerted to an error before the event loop is
358
- allowed to continue.
353
+ useful for the user to be alerted to an error before the event loop is
354
+ allowed to continue. Here is the previous example using ` process.nextTick() ` :
355
+
356
+ ``` js
357
+ function someAsyncApiCall (callback ) {
358
+ process .nextTick (callback);
359
+ };
360
+
361
+ someAsyncApiCall (() => {
362
+ console .log (' bar' , bar); // 1
363
+ });
364
+
365
+ var bar = 1 ;
366
+ ```
359
367
360
- A real world example in node would be :
368
+ Here's another real world example:
361
369
362
370
``` js
363
371
const server = net .createServer (() => {}).listen (8080 );
@@ -367,10 +375,10 @@ server.on('listening', () => {});
367
375
368
376
When only a port is passed the port is bound immediately. So the
369
377
` 'listening' ` callback could be called immediately. Problem is that the
370
- ` .on('listening') ` will not have been set by that time.
378
+ ` .on('listening') ` will not have been set by that time.
371
379
372
380
To get around this the ` 'listening' ` event is queued in a ` nextTick() `
373
- to allow the script to run to completion. Which allows the user to set
381
+ to allow the script to run to completion. Which allows the user to set
374
382
any event handlers they want.
375
383
376
384
## ` process.nextTick() ` vs ` setImmediate() `
@@ -389,7 +397,7 @@ percentage of the packages on npm. Every day more new modules are being
389
397
added, which mean every day we wait, more potential breakages occur.
390
398
While they are confusing, the names themselves won't change.
391
399
392
- * We recommend developers use ` setImmediate() ` in all cases because its
400
+ * We recommend developers use ` setImmediate() ` in all cases because it's
393
401
easier to reason about (and it leads to code that's compatible with a
394
402
wider variety of environments, like browser JS.)*
395
403
@@ -413,11 +421,11 @@ server.listen(8080);
413
421
server .on (' listening' , function () { });
414
422
```
415
423
416
- Say that listen() is run at the beginning of the event loop, but the
424
+ Say that ` listen() ` is run at the beginning of the event loop, but the
417
425
listening callback is placed in a ` setImmediate() ` . Now, unless a
418
- hostname is passed binding to the port will happen immediately. Now for
419
- the event loop to proceed it must hit the ` poll ` phase, which means
420
- there is a non-zero chance that a connection could have been received
426
+ hostname is passed binding to the port will happen immediately. Now for
427
+ the event loop to proceed it must hit the ** poll** phase, which means
428
+ there is a non-zero chance that a connection could have been received
421
429
allowing the connection event to be fired before the listening event.
422
430
423
431
Another example is running a function constructor that was to, say,
0 commit comments