concept

JavaScript has a concurrency model based on event loops, which are responsible for executing code, collecting and processing events, and executing subtasks in queues. This model is quite different from models found in other languages, such as C and Java. (From MDN)

To put it simply, for the tasks in JS operation, JS has a special mechanism to deal with collection, queuing and execution, which is called Event Loop.

To better understand the event loop, let’s look at a few related concepts

Single thread

We all know that JS is single threaded, what does that mean?

JS single threading refers to the fact that javascript engines (such as V8) can only handle one task at a time.

One might ask, isn’t ajax an asynchronous task that can be executed at the same time as JS code?

The answer is yes, but this does not conflict with JS single threading, as stated earlier javascript engines such as V8 can only handle one task at a time. However, this does not mean that the browser can only handle one thing at a time. In fact, asynchronous tasks such as Ajax are not run on the JS engine. Ajax is executed in the module that the browser processes the network, so it does not affect the JS engine’s task processing.

It is important to note that only one task can be processed at a time, which does not mean that only one function is being processed at the same time. We can have multiple functions being processed and multiple execution environments at the same time, which will be discussed later.

The execution environment

About the execution environment can refer to my previous blog on THE JS execution environment and scope.

Execution environment is the environment in which JS code statements are executed, including global execution environment and function execution environment.

  • Global execution environment: The global execution environment is the most peripheral execution environment. The object representing the execution environment varies depending on the host environment in which the ECMAScript implementation is implemented. On the Web, the global execution environment is referred to as the Window object.

  • Function execution environment: Each function has its own execution environment.

When a task is executed, it will correspond to a dynamically changing execution environment stack. This execution environment stack includes different execution environments, which is a lifO structure.

Taking the following code as an example, let’s look at the dynamic change of the execution environment stack

function Fn1() {
  var a = 1;

  function Fn2() {
      var b = 2;
  }
  Fn2(); // When the program runs to this point
}

Fn1();
Copy the code

The variable object

For variable objects, please refer to my previous blog on JS execution environment and scope

Each execution environment has a variable object associated with it, which contains all variables and functions defined in the execution environment. (Consider why we advocate creating as few global variables as possible. The answer is that the variable objects corresponding to the global environment are always in memory.)

Event loop mechanism

Let’s start with a picture on MDN

The diagram above shows the event loop mechanism in JS well. We can see that the diagram mainly includes three parts: Stack, Heap and Queue, which are analyzed one by one.

  • Stack represents the Stack structure of the computer, where the Stack area represents the task (a task) being processed by the current JS thread. Together with the execution environment section, we can actually think of this combination of frames as the current execution environment stack. A Frame represents an execution environment. It is also explained that a task can contain multiple related functions.

  • Heap is generally used to represent computer memory, where Heap represents the relevant data under the current task, combined with the above concept of variable Object, we can regard the Object label as a variable Object corresponding to the execution environment. When an execution environment is pushed into the execution environment stack, a variable object is created and placed in the Heap. When the execution environment stack is pushed out of the execution environment, its corresponding variable object is removed from the Heap and destroyed. If we dig a little deeper, we can see that the set of Object is actually the set of variable objects in our scope chain.

  • Queue represents a Queue in a computer and is a first-in, first-out data structure. Here the Queue area represents the set of tasks currently being queued, which is called the task Queue. A Message represents a task to be executed, and they are queued in order.

By analyzing the different areas of the image, we can easily figure out the mechanism of the event environment illustrated in this image

  1. The JS thread performs only one task at a time, during which multiple function execution environments may be created, corresponding to frames.

  2. In the execution of the task, the dynamic change of the environment stack is implemented at any time, and the corresponding variable Object is constantly created and destroyed, corresponding to Object.

  3. When asynchronous tasks such as Ajax I/O get results, their callback is added as a task to the task queue and queued up for execution.

  4. When the task in the JS thread is finished, the task Queue will be read, and the first task in the Queue will be added to the JS thread and executed.

  5. After the asynchronous task is completed, the task is continuously added to the task queue. When the thread is idle, the task is read from the task list and executed.

Macro and micro tasks under the event loop

We usually divide asynchronous tasks into macro tasks and micro tasks. They are distinguished by:

  • Macro task: Generally, the callback task is generated by the communication between the JS engine and the host environment, such as setTimeout. SetInterval is timed by the browser. The execution time of the callback function needs to be notified to the JS engine by the browser, the network module, and the communication callback processed by I/O. SetTimeout, setInterval, DOM event call-back, Ajax callback after the end of the request, overall script code, setImmediate.

  • Micro-task: This is usually a callback generated when a macro task is executed in a thread, such as Promise, process.nextTick, Object.observe(deprecated), and MutationObserver (DOM listener). These are all callbacks that the JS engine can listen for.

We have seen the classification of macro tasks and micro tasks, so why do we divide them into macro tasks and micro tasks? This is mainly due to the different mechanism by which they are added to the task queue in the event loop.

In the event loop, the task is usually performed by the macro task start (JS code to load the execution), in the macro task execution process, may produce new macro and micro tasks, then macro tasks (such as ajax callback) will be added to the end of the task queue waiting for the event loop mechanism, and micro task will be added to the front end of the current task queue, Also waiting for the event loop mechanism to execute.

Macro or micro tasks of the same type are sorted according to the sequence of callback, while tasks of different task types have certain priorities and are distinguished according to different types of tasks

SetImmediate > MessageChannel > setTimeout/setInterval

Microtask priority, process.nextTick > Promise > MutationObserver

An 🌰

Let’s analyze the print order of the following code

// setTimeout1
setTimeout(() = > {
  console.log(1)

  new Promise((resolve) = > {
    resolve()
  // Promise1
  }).then(() = > {
    console.log(2)}); })// setTimeout2
setTimeout(() = > {
  console.log(3)})new Promise((resolve) = > {
  console.log(4)
  resolve()
  console.log(5)
// Promise2
}).then(() = > {
  console.log(6)})console.log(7)

new Promise((resolve) = > {
  resolve()
// Promise3
}).then(() = > {
  console.log(8)})Copy the code

Let’s assume that this code is executing in a JS thread (script code is a macro task), generating asynchronous tasks, setTimeout and Promise. SetTimeout is a macro task, and Promise is a micro task.

According to the above macro task, micro task adding mechanism in the task queue, we can get the task queue in the process of code execution will be shown as follows

After analyzing the task queue, we can easily get the print order

First, execute the macro task and print 4, 5, and 7 from top to bottom

Then the asynchronous tasks are executed in the sequence of the task queue, printing 6, 8, 1, 2, and 3 in sequence

conclusion

This is my understanding of Event Loop. JS event loop mechanism is a very basic concept, master it can help us understand the code in JS execution order and principle, I hope that whether beginners or have a certain basis of the students can really understand. Welcome to point out and add comments if there is any misunderstanding or confusion in this article.

reference

  • Thoroughly understand browser event-loop

  • Macro and micro tasks in JavaScript

  • “1 minute – Front-end 08” JS macro tasks and micro tasks


Welcome to front end learning punch card group learning ~ 516913974