Why learn about event loops

Only when we understand how the event loop works, and write it into our minds, do we have more control over how JavaScript works as a whole, and it profoundly affects the way we think about code when we program.

The single-threaded JavaScript language means that only one task can be handled at a time, executing one line of code. To keep the program running smoothly, the event loop mechanism coordinates events, user web interaction, scripting, UI rendering, and asynchronous network requests so as not to block the main thread.

JavaScript processes tasks in a continuous loop between waiting tasks, executing tasks, and sleeping for new tasks, also known as an event loop. Tasks include Script (whole code), setTimeout, setInterval, DOM rendering, DOM events, Promises, XMLHTTPREQUEST, and so on

1. The tasks in the task queue are executed only after the tasks in the main thread are completed

2. When a new task arrives, it will be put into the queue and execute the task in the queue according to the first-in-first-executed policy

3. For example, if multiple setTimeout times reach the time at the same time, they should be executed in sequence

Execution stack

A “call stack,” as it is known in other programming languages, is a stack with LIFO (LIFO) data structures that are used to store all execution contexts created while the code is running.

The main thread

To be clear, the main thread is a different concept from the execution stack. The main thread specifies which event in the execution stack is now executed. Main thread loop: that is, the main thread constantly reads events from the stack and executes all synchronized code in the stack. When an asynchronous event is encountered, instead of waiting for the asynchronous event to return a result, the event is suspended in a separate Queue from the execution stack, called a Task Queue.

Process description:

1. Execute the macro task script in line 1 and print the output

3, execute to Promise, encounter first then(). This is a microtask. Put it in the microtask queue

4. Execute line 15 of the main thread code, output

Event loop

6. In the same event cycle, because the priority of the microtask is higher than that of the macro task, even if the setTimeout timer just entered the macro task queue first and promise.then() entered the microtask queue later, the microtask code was still pushed to the execution stack first, and then the execution ended and output

After promise1 is printed, proceed with the second promise.then(), as in Step 2, and put the task into the microtask queue. The main thread is empty. Then check whether there are any more tasks in the microtask queue, read the promise2 microtask, push it to the stack, and output:

The timer

SetTimeout Adds to a new Task after the delay expires

Macro Task (Task)

In an event loop, the browser can rerender the page after each Task has finished and before the next Task has started. The setTimeout delay may not be precise, because it is added to a new Task after the setTimeout delay, rather than executed immediately, and can only be executed after the execution of the previous Task is completed, and the execution time cannot be guaranteed.

Micro tasks (Microtask)

The need to execute all microTasks immediately after the current Task completes, without reassigning a new macro Task, reduces the performance overhead. From the analysis of the output above, you should know that the MicroTask queue is a separate queue from the task queue, and the MicroTask will be executed after each task task is finished. Microtasks generated in each task are successively added to the MicroTask queue. The microtasks generated in the microTask queue are added to the end of the current queue, and the MicroTask processes all tasks in the queue in sequence. Microtasks-type tasks currently include MutationObserver and Promise callback functions.

To consider

Does the browser UI still respond when switching pages (tabs)?

Microtask queue
empty

Is there a stack overflow error?

The two examples above nicely illustrate the difference between macro and micro tasks in event loops.

conclusion

JavaScript is a single-threaded language. Asynchronous operations are placed in an event loop queue waiting for the main execution stack. There is no special asynchronous execution thread. Second, microtask takes precedence over macro task execution. So if there is logic that is expected to be executed first, putting it into the microtask queue will result in the macrotask queue being executed earlier. In an event loop, the browser can rerender the page after each Task has finished and before the next Task has started.

The first code word, if there is any incorrect place, I hope the old teacher passing by will not hesitate to give advice, if you feel that there is no waste of time, please point a thumbs-up!

Understand JavaScript event loops in depth