This is the 23rd day of my participation in Gwen Challenge

Event Loop is a kind of operation mechanism of computer system, which is a very important concept. JavaScript uses this mechanism to solve the problem of single-threaded running. This familiarity will make it easier to understand vUE’s asynchronous events.

JavaScript is single-threaded

1. What is single threading?

Single thread in program execution, the path of the program in sequential order, the first must be processed before the next can be executed. Simply put, you can only do one thing at a time.

2. Why is JS single threaded?

Js is a simple scripting language that runs on web pages. It was originally designed as a browser scripting language to interact with users and manipulate the DOM. This determines that it is single-threaded.

3. Problems with single threads?

Single-threaded means that all tasks need to be queued until the first one is finished before the next one can be executed. If the first task takes a long time, the second task will have to wait forever. This can lead to wasted performance when IO operations are time-consuming but CPU idle.

4. How to solve the performance problem of single thread?

It can be solved asynchronously. The main thread can suspend the waiting task and run the next task first, regardless of the IO operation. Wait until the IO operation returns the result, then go back and continue the pending task. Therefore, all tasks can be divided into two types, one is synchronous task, the other is asynchronous task.

Execution stack and task queue

Execution stack

When a function is executed, the user clicks the mouse once, Ajax completes, an image is loaded, etc., as long as the callback function is specified, these events will be put into the execution stack queue, waiting for the main thread to read, following the first-in, first-out principle.

Task queue

When an asynchronous event is encountered, instead of waiting for the asynchronous event to return a result, the event is suspended in a queue separate from the execution stack, called a task queue. It is important to note that asynchronous tasks must specify a callback function. When the main thread starts executing an asynchronous task, it executes the corresponding callback function.

Event Loop

JavaScript memory model

Before understanding event loops, it is important to understand the Js memory model, which will help you understand event loops better.

  • Call Stack: Used for execution of main thread tasks.
  • Heap: Used to hold unstructured data, such as programmatically assigned variables and objects.
  • Task Queue: Stores asynchronous tasks.

Js asynchronous execution of the operation mechanism

  • All synchronization tasks are executed on the main thread, forming an execution stack.
  • In addition to the main thread, there is a task queue. Whenever an asynchronous task has a result, an event is placed in the task queue.
  • Once all synchronization tasks in the execution stack have been executed, the system reads the task queue to see what events are in it. Those corresponding asynchronous tasks then end the wait state, enter the execution stack, and start executing.
  • The main thread repeats step 3 above.

Task queue

Asynchronous tasks are divided into macrotasks and microtasks. Tasks registered by different APIS will enter their corresponding queues one by one, and then wait for the Event Loop to push them into the execution stack for execution.

  • Most of the macro tasks include: Script, setTimeout, setInterval, I/O, UI interaction events, and setImmediate(node.js).
  • Microtasks mainly include: Promise, MutaionObserver, process.nexttick (Node.js environment)

Our JavaScript execution process is single-threaded, and all tasks can be thought of as being stored in two queues — the execution queue and the event queue.

The execution queue is the task for all the synchronous code, the event queue is the macro task for all the asynchronous code, and our micro task is in between the two queues.

When JavaScript is executed, all synchronous codes will be executed first, and the corresponding asynchronous code will be stored in the corresponding queue according to its task type (macro task is put into the event queue, micro task is put into the execution queue, before the event queue). When the synchronous code is executed, the microtask between the execution queue and the event queue is executed, followed by the macro task in the event queue.

new Promise(resolve= > {
    resolve(1);
    
    Promise.resolve().then(() = > {
        // t2
        console.log(2)});console.log(4)
}).then(t= > {
    // t1
    console.log(t)
});
console.log(3);
Copy the code

The flow of this code is roughly as follows:

  • The script task runs first. The Promise instance is encountered first, and the constructor executes first, so 4 is printed first. In this case, microTask has tasks T2 and T1
  • The script task continues with output 3. At this point, the first macro task is complete.
  • Perform all microtasks, take out T2 and T1 successively, and output 2 and 1 respectively
  • Code execution complete

To sum up, the output of the above code is: 4321

Event loop

The main thread reads events from the task queue in a continuous Loop, so the whole operation mechanism is also called an Event Loop.

From the picture above, we can see that:

  • When the main thread runs, it generates heap and stack.
  • The code in the stack calls various external apis, which add various events (click, load, done) to the “task queue”.
  • When the stack completes, the main thread reads the task queue and executes the callback function corresponding to those events.