Node.js Event Loop Explained

Software Developer Diaries
21 Jul 202410:25

Summary

TLDRThis video dives into the Node.js event loop, explaining its various stages and how they interact to handle asynchronous operations. It starts by detailing how the event loop runs continuously when a server is active, handling timers, callbacks, and other tasks. The video also covers the differences between microtasks and macrotasks, and their priorities in the loop. The creator emphasizes the importance of understanding these details for optimizing Node.js applications, and hints at future videos on improving performance and avoiding event loop blocking.

Takeaways

  • 🔄 Node.js has an event loop that operates continuously, especially when running processes like a web server.
  • ⏳ The first phase of the event loop is called 'timers', where functions like `setTimeout` and `setInterval` are checked and executed.
  • 📋 Microtasks, such as `process.nextTick()` and promises, have higher precedence than macrotasks like timers and I/O operations.
  • ⚙️ The V8 engine, which powers Node.js and browsers, separates tasks into microtasks and macrotasks, with microtasks running first.
  • ⏱️ Inside the timers phase, microtasks and macrotasks run with their own order of precedence.
  • ⏲️ The 'poll' phase of the event loop is crucial for handling incoming I/O operations such as network requests and file reads.
  • 💻 Understanding the internal workings of the event loop helps in optimizing Node.js applications for performance.
  • 🕒 The 'check' phase is specifically for handling `setImmediate`, which executes with higher precedence over other timers.
  • ❌ The last phase, 'close callbacks', handles events like socket closures and cleanup operations.
  • 📊 Optimizing Node.js performance involves reducing event loop lag and avoiding blocking operations, with strategies like using worker threads.

Q & A

  • What is the event loop in Node.js and when does it start?

    -The event loop in Node.js starts as soon as you run a Node.js script (e.g., `node index.js`). It is responsible for handling asynchronous operations, and it keeps running as long as there are tasks, such as web servers, waiting for events like incoming network connections.

  • What happens in the 'timers' phase of the Node.js event loop?

    -In the 'timers' phase, Node.js checks for and processes any scheduled functions that were set using `setTimeout` or `setInterval`. These are executed in the order they were set, based on their delay times.

  • What are microtasks and how do they differ from macrotasks in Node.js?

    -Microtasks have a higher priority than macrotasks and are executed before macrotasks in the event loop. Examples of microtasks include promise callbacks, `process.nextTick`, and `queueMicrotask`. Macrotasks include `setTimeout`, `setInterval`, and I/O operations like network requests.

  • What is the priority order for tasks within the 'timers' phase?

    -The priority order is: synchronous code, `process.nextTick` (next tick queue), microtasks (e.g., promise callbacks), and finally macrotasks (timers like `setTimeout` and `setInterval`).

  • What role do 'pending callbacks' play in the Node.js event loop?

    -The 'pending callbacks' phase handles callbacks from I/O operations that were deferred in the previous cycle of the event loop. These callbacks are executed in this phase after all timers and microtasks are processed.

  • What is the 'poll' phase and why is it considered the most important part of the event loop?

    -The 'poll' phase is where most of the asynchronous operations happen, such as incoming connections (HTTP, TCP) and file I/O. It checks for new events and handles them, making it critical for performance in a Node.js application.

  • What is the significance of 'setImmediate' in Node.js?

    -`setImmediate` is a special function in Node.js that schedules code to run at the next iteration of the event loop. It has a higher precedence than normal timers (`setTimeout`) and is executed in the 'check' phase.

  • What is the 'close callbacks' phase in the Node.js event loop?

    -The 'close callbacks' phase is the final step of the event loop, where it handles callbacks for closing events, such as when a TCP connection or file stream is closed.

  • Why is understanding the event loop important for Node.js developers?

    -Understanding the event loop helps developers write more efficient and optimized code by knowing how asynchronous tasks are handled, how to prevent blocking the event loop, and when to use certain functions like `setImmediate`, `process.nextTick`, and microtask queues.

  • What is 'event loop lag' and how can it affect the performance of a Node.js application?

    -Event loop lag occurs when long-running operations or synchronous code block the event loop, preventing it from handling other tasks. This can degrade the performance of a Node.js application, especially in cases involving high concurrency or heavy I/O.

Outlines

00:00

🌀 Understanding the Node.js Event Loop

The Node.js event loop is a fundamental yet often misunderstood aspect of Node.js, rarely covered in detail by videos or blogs. The event loop consists of multiple stages that occur rapidly while a Node.js application is running. This section introduces the concept, noting that as soon as a Node.js app is executed, the event loop begins. For small scripts, the loop may start and stop quickly, but for web servers, it persists, waiting for incoming events such as TCP connections. Understanding these details is crucial for leveraging Node.js effectively.

05:01

⏲️ Event Loop Stages and Timer Handling

This part delves deeper into the event loop, specifically focusing on the timer phase. It explains that Node.js checks for timers like `setTimeout` and `setInterval` during this phase. Through an example code with multiple timeouts and microtasks, the section introduces the concept of task queues—microtasks and macrotasks—highlighting their different priorities. Microtasks like promises and `process.nextTick()` take precedence over macrotasks like timeouts and intervals. The importance of understanding this hierarchy in developing efficient Node.js applications is emphasized.

10:03

🔄 Precedence and Task Queues in Node.js

Here, the script explains how task execution in Node.js is further subdivided into queues within each phase of the event loop. Tasks like `nextTick` are manually fired and take precedence even within `setTimeout`. This hierarchy is crucial for managing the flow of synchronous and asynchronous operations. The example illustrates how microtasks, promises, and other operations are prioritized, ensuring that developers understand how to manage task execution efficiently within the event loop.

📋 Pending Callbacks and Polling Phase

The focus shifts to the 'pending callbacks' phase and the 'poll' phase, which is where most asynchronous operations, such as network connections and file system reads, are handled. The poll phase plays a key role in ensuring the performance of a Node.js app. There’s a brief mention of optimizations, particularly how to avoid blocking the event loop and ensuring smooth operation. The video promises a follow-up on optimizing Node.js applications for performance by effectively managing these phases.

✅ The Check Phase and SetImmediate

This section introduces the 'check' phase, which is responsible for handling `setImmediate`, a function similar to `setTimeout` but with a higher precedence in the event loop. The script explains how `setImmediate` can either execute immediately during the poll phase or be deferred, depending on the system’s decisions. The final stage, 'close callbacks', is briefly mentioned, noting its role in managing events like socket closures.

👋 Wrapping Up and Future Topics

In the final paragraph, the speaker wraps up the video, reiterating that the discussion was an overview of the Node.js event loop. While optimizations and detailed explanations were not covered, the speaker promises a future video on how to optimize performance, particularly avoiding event loop lag. The video ends with a call to action for viewers to subscribe and await the next tutorial.

Mindmap

Keywords

💡Event Loop

The event loop is a core concept in Node.js that handles asynchronous operations. It continuously checks for tasks, executes them, and then waits for new tasks to arrive. In the video, it is explained as a looping process that starts with the node script and keeps running to manage operations like handling incoming connections, reading files, or managing timers.

💡Timers

Timers in Node.js, such as `setTimeout` and `setInterval`, are used to schedule tasks for future execution. In the event loop, the 'timers' phase checks if any timers are due to execute. The video explains how the event loop processes these timers and gives them priority based on whether they are synchronous or asynchronous.

💡Microtasks

Microtasks are tasks that have a higher priority in the Node.js event loop. They include promise callbacks, `process.nextTick()`, and mutation observers. The video emphasizes that microtasks take precedence over macrotasks, meaning they are executed before most other operations within each phase of the event loop.

💡Macrotasks

Macrotasks, also known as regular tasks, include `setTimeout`, `setInterval`, and I/O operations like network requests or file reading. In the video, macrotasks are described as lower priority compared to microtasks, and they are handled during the appropriate phase of the event loop, such as timers or poll.

💡Pending Callbacks

Pending callbacks are callbacks that were deferred from previous phases of the event loop, such as I/O operations that could not be completed immediately. The video explains how pending callbacks get executed after timers and how they are processed during the 'poll' phase.

💡Poll

The 'poll' phase in the event loop is responsible for executing most of the application’s I/O operations, such as handling incoming connections or reading files. It is one of the most critical stages, as described in the video, where the performance of the application is largely determined.

💡setImmediate

`setImmediate` is a special kind of timer in Node.js that is executed in the 'check' phase of the event loop. Unlike `setTimeout`, it has higher precedence and will execute after the poll phase completes. The video highlights this distinction, noting that `setImmediate` can provide more control over timing.

💡process.nextTick()

`process.nextTick()` is a method in Node.js that schedules a callback to be invoked in the next iteration of the event loop, but before any I/O tasks. It is treated as a microtask, giving it high priority. In the video, it's explained as a powerful tool for ensuring that critical code runs before other tasks.

💡Event Loop Lag

Event loop lag refers to a delay in the execution of tasks due to blocking operations, preventing the event loop from executing efficiently. The video briefly mentions how poorly optimized code can cause event loop lag, and how understanding the event loop helps developers avoid this issue.

💡Close Callbacks

Close callbacks are executed during the final phase of the event loop and handle tasks related to closing resources like socket connections. The video describes how these callbacks listen for 'close' events and ensure that resources are properly cleaned up when connections are terminated.

Highlights

Node.js Event Loop consists of multiple steps, occurring within milliseconds during the execution of a Node.js application.

When a Node.js app starts, the event loop initiates, running continuously unless the app terminates or a server is actively waiting for TCP connections.

The first step of the Event Loop is 'timers,' which handles functions like `setTimeout` and `setInterval`.

Microtasks and macrotasks have different levels of precedence in Node.js. Microtasks (like Promise callbacks and process.nextTick) are higher priority than macrotasks (like setTimeout, I/O operations, and event handlers).

The `nextTick` queue is manually triggered, and its tasks are executed first within a timeout, even before other microtasks and macrotasks.

Promise callbacks are considered microtasks, so they have a higher precedence and are executed before macrotasks like setTimeout or setInterval.

The 'poll' phase in the Event Loop is critical as it handles most I/O operations, including incoming HTTP or TCP connections, file reading, and more.

Pending callbacks are deferred tasks that were not executed in the previous cycle of the Event Loop and will be processed in the next round.

In the 'idle and prepare' phase, Node.js performs bookkeeping tasks, but it does not impact application performance or behavior.

SetImmediate has a higher precedence than setTimeout or setInterval and is executed during a specific step in the Event Loop.

The 'check' phase is where setImmediate is executed, giving it precedence over standard timers.

Close callbacks are triggered when a socket or any other connection is closed, allowing developers to clean up resources and manage disconnection events.

Understanding the internals of the Event Loop helps developers optimize Node.js applications and avoid blocking the Event Loop, ensuring high performance.

Event Loop lag is a critical issue to avoid, as it can delay execution of asynchronous tasks, degrading the performance of the Node.js application.

The speaker plans to release further content about optimizing Node.js performance, focusing on using worker threads and ensuring non-blocking operations.

Transcripts

play00:00

we are missing some very important

play00:02

knowledge about the event Loop of

play00:05

node.js because I feel like this is not

play00:07

really covered in many videos and blog

play00:09

articles but nodejs event Loop actually

play00:12

consists of many steps that are going

play00:14

through that are happening within every

play00:16

millisecond when you are running a no JS

play00:19

app so let's talk about this and what

play00:21

are the implications and what you need

play00:23

to be aware of so first of all nodejs

play00:27

does have an event Lo okay if you go to

play00:29

the official noj website you will see

play00:31

that there's a big article on how the

play00:34

event Loop Works actually and the all

play00:36

the steps that we're going to talk about

play00:38

now so let's go back to the Blackboard

play00:41

and this round figure that you see here

play00:44

that goes clockwise is basically an

play00:46

event Loop that starts as soon as you

play00:49

run a node script okay you run node

play00:52

index.js your app starts and as soon as

play00:55

your app starts or the process starts

play00:58

the loop starts as well well now the

play01:00

thing is if you only have a very few

play01:04

lines of code within your index.js file

play01:07

let's say you're just doing a console

play01:08

log or something like that the app is

play01:10

going to start the event Lo is going to

play01:12

start as well and then it's going to

play01:14

close it's going to exit because your

play01:16

process stopped there's nothing that we

play01:18

need to listen to on the other hand if

play01:21

you're starting a web server as you know

play01:23

when you start the web server you do

play01:25

this thing server. listen and under the

play01:27

hood it basically waits for TCP

play01:31

connections and the event Loop does not

play01:34

stop it just keeps going and it's

play01:37

basically going through these all steps

play01:40

waiting for some events to happen and

play01:43

this is the crucial part of

play01:44

understanding how the event Loop works

play01:46

okay so let's call this one the event

play01:50

Loop e l just so that we know what we're

play01:53

referring to so as soon as the event

play01:55

Loop starts we are going to go all of

play01:58

these over all of these steps like many

play02:00

times within one second okay so what is

play02:03

happening in the very first step called

play02:05

timers well it turns out that nodejs is

play02:09

checking for timers that are available

play02:12

okay so if you have done a a timeout set

play02:15

set timeout or set interval they're are

play02:17

going to be handled within this uh part

play02:20

here in in set timeouts or in the timer

play02:23

section okay let's look at this piece of

play02:26

code and understand what

play02:30

has precedence when we are in this step

play02:33

timers okay so we're going to see that

play02:35

we have a console log or first of all we

play02:38

have three timeouts we have a console

play02:40

loog set timeout one then we have a

play02:43

resolve and reject and then we have some

play02:46

function called q microtask and then we

play02:49

have nexti what are these because if you

play02:53

go for a normal no JS tutorial video

play02:56

you're not going to know anything about

play02:58

this this is like very lowlevel node.js

play03:00

stuff but let me explain I think if you

play03:03

are using node.js as your tool to

play03:05

accomplish your business needs the

play03:07

better you know the underlying

play03:09

Technologies of your tool or how it

play03:11

works under the hood the better equipped

play03:14

you are okay so it turns out let me

play03:18

switch to another page uh nodejs or

play03:21

basically the engine V8 engine that

play03:23

nodejs is based upon it's it applies the

play03:27

same for the browsers um they have

play03:29

microt tasks and macro tasks meaning

play03:33

microt tasks are more important so they

play03:36

have higher priority than M microtasks

play03:39

microtasks include promise callbacks

play03:42

mutation observe API uh process.

play03:45

nexttick which is a method that we can

play03:46

fire manually within nodejs Q microtask

play03:49

function that we basically sew and

play03:52

weight Expressions on the other hand

play03:54

microtasks or macro tasks consist of set

play03:57

timeouts set intervals D manipulation IO

play04:00

operations for example reading a file

play04:02

Network requests and event handlers now

play04:05

what does it mean for us so in this

play04:07

timeout we're going the president is

play04:09

going to be like the following so we

play04:11

enter the timeout okay we're going to

play04:13

log the first thingy because conso loog

play04:17

is actually synchronous so we're going

play04:19

to stumble upon this and it's going to

play04:21

be locked out next what what's going to

play04:24

happen are we going to L out the

play04:27

promises or are we going to look out the

play04:30

Q microtask or the next tick this is a

play04:33

very interesting question and the answer

play04:36

is actually here so we have these three

play04:39

bubbles here which are also kind of a

play04:41

loop within the loop all right and all

play04:45

of these three bubbles actually are

play04:48

living within every step that we have

play04:51

here so they're inside the timers

play04:53

they're also inside the pending call

play04:55

bags they're also inside the pole so

play04:58

they are running under every step and

play05:00

they also have a precedence okay I know

play05:02

this is confusing but first of all we

play05:05

have these steps and then we have a

play05:06

precedence within each queue so the next

play05:10

TI queue is the one that we are firing

play05:13

manually okay here for example we do

play05:16

next tick and then we do console log so

play05:19

that's going to fire first meaning

play05:21

within our set timeout we're going to

play05:23

get next tick one first the next thing

play05:26

that's going to happen is we're going to

play05:29

look for microtasks microtasks are the

play05:32

ones that we already discussed for

play05:33

example promises so promises are going

play05:36

to have a higher precedence and then we

play05:38

are going to fire the Q microtask which

play05:41

also basically related to a microtask

play05:44

and then we're going to look for the

play05:47

macro tasks okay in this case we don't

play05:50

have any macro tasks in this piece of

play05:51

code but you can imagine that it will

play05:53

fire next as soon as these all three are

play05:57

done within our first timeout and

play05:59

remember that we're still in this

play06:01

section here we're going to jump to the

play06:04

second time out so basically event Loop

play06:07

starts we go to the timers section and

play06:10

the timers also have its own precedence

play06:13

so it's going to make sure that

play06:14

everything has run here has around here

play06:17

and then has around here and then we

play06:19

jump to the next basically function

play06:22

within the timers and as soon as these

play06:24

are done now the event Lo can proceed to

play06:27

pending callbacks what is pending

play06:29

callbacks basically every time we're

play06:32

going to come to this the poll section

play06:34

is pretty much the most important one

play06:37

it's the one that executes most of the

play06:39

stuff including the synchronous stuff

play06:41

okay sometimes poll does not poll stage

play06:45

does not execute things and it defers

play06:47

them it defers them to the next round

play06:50

trip of the event Loop and sometimes

play06:54

basically from the previous round things

play06:56

end up here pending callbacks for

play06:58

example a timeout can end up there for

play07:01

one or other reason so so as you know

play07:04

pending callbacks are going to as I

play07:07

mentioned also have this precedence of

play07:09

three different types of cues and it's

play07:12

going to execute them one by one as soon

play07:14

as the pending callbacks have been

play07:16

executed we're going to jump to the next

play07:18

section called idle and prepare there's

play07:22

nothing to cover there because it is

play07:24

it's native to V8 or nodejs and it's

play07:28

basically doing some bookkeeping under

play07:30

the hood to make sure that we're intact

play07:33

so there's no impact for us when it

play07:35

comes to the optimizations that we can

play07:37

make okay so the next point will be poll

play07:41

as I said this is the most important one

play07:44

why because this is where the incoming

play07:47

connections for example uh HTTP or TCP

play07:50

connections that are being established

play07:52

socket connections and so on file

play07:54

reading all the synchronous stuff is

play07:56

going to happen here and this is exactly

play07:59

where we need to make sure that our

play08:02

basically our app is performant wor not

play08:07

I'm going to release another video as

play08:09

soon as possible probably most after

play08:12

this one in order to learn how to

play08:15

actually make your node.js app

play08:17

performance do you do you need new

play08:19

worker threats do you need how do you

play08:21

make everything asynchronous and most of

play08:24

all

play08:25

how basically how not to block the event

play08:28

Loop and there's a thing called uh event

play08:31

Loop lag basically when your operations

play08:35

are executed with a small like it's

play08:38

really hard to control that and I'm

play08:39

going to cover that in the next video as

play08:41

well so stay tuned And subscribe if you

play08:44

haven't yet now we covered the polling

play08:47

okay so we're going to execute mple

play08:48

tasks here and then we also have a thing

play08:51

called check okay what is a check well

play08:55

we're basically checking for one and

play08:57

only thing think called set set

play08:59

immediate yeah you might not heard heard

play09:01

about that we have set inter set timeout

play09:04

set interval and we also have a set

play09:07

intermediate here it works the same way

play09:10

as a set timeout or sent interval but

play09:14

the difference is that it has a presence

play09:16

because it's happening within the event

play09:19

Loop so basically if you have a set

play09:22

inter immediate in your code it's going

play09:25

to be executed right here on the other

play09:27

hand set timeout can either be executed

play09:30

in a timers depending on what what your

play09:34

operating system decides during the poll

play09:36

event or it can be deferred to the next

play09:39

round okay so set immediate basically

play09:42

has a higher precedence than other

play09:45

timers and then we also have the last

play09:47

step called close callbacks basically

play09:50

these are going to listen for uh close

play09:53

events for example when you're closing

play09:55

the socket connection or when you are

play09:59

manually closing the call bags or uh

play10:02

removing the call bags this is it what I

play10:06

wanted to tell you guys in this video

play10:08

this is was this was just an rough

play10:11

overview of the internals of the event

play10:12

Loop of nodejs and as I said all the

play10:15

optimizations optimization topics are

play10:17

going to be covered in the next video so

play10:19

smash like subscribe and I will see you

play10:21

in the next one goodbye

Rate This

5.0 / 5 (0 votes)

Etiquetas Relacionadas
Node.js BasicsEvent LoopJavaScript PerformanceAsynchronous CodeSetTimeoutMicrotasksV8 EngineOptimizing Node.jsTimersPromises
¿Necesitas un resumen en inglés?