头图

Understand once-the macro tasks and micro tasks of the JS event loop

As we all know, JS is a single-threaded language, but browsers can handle asynchronous requests well, so why?

The execution environment of JS is generally browser and Node.js, the two are slightly different, here we only discuss the situation in the browser environment.

There are two kinds of tasks during the execution of JS, namely: synchronous tasks and asynchronous tasks.

  • Synchronous tasks: such as declaration statements, for, assignments, etc., are executed immediately from top to bottom and from left to right after reading.
  • Asynchronous tasks: such as ajax network requests, setTimeout timing functions, etc. are all asynchronous tasks. Asynchronous tasks will be coordinated through the event queue mechanism (first in, first out mechanism).

Event Queue

The tasks in the task queue are also divided into two types, namely: Macro-take and Micro-take

  • Macro tasks mainly include: scrip (JS overall code), setTimeout, setInterval, setImmediate, I/O, UI interaction
  • Micro tasks mainly include: Promise (focus on), process.nextTick (Node.js), MutaionObserver

Execution of the task queue is: to execute a macro task , during execution if the output of the new macro / micro tasks, it will push them into the corresponding task queue, in the implementation of a micro-task team after , after again Execute the macro task, and so on. repeated process above 1609e35142389f is called Event Loop .

Each cycle operation is called tick .

Understand the execution process of micro tasks and macro tasks

console.log("script start");

setTimeout(function () {
  console.log("setTimeout");
}, 0);

Promise.resolve()
  .then(function () {
    console.log("promise1");
  })
  .then(function () {
    console.log("promise2");
  });

console.log("script end");

According to the above content, analyze the execution steps:

  1. Macro task: execute the overall code (equivalent to the code in <script>

    1. Output: script start
    2. Encounter setTimeout, join the macro task queue, the current macro task queue (setTimeout)
    3. When you encounter a promise, join the micro task, the current micro task queue (promise1)
    4. Output: script end
  2. Micro task: Execute the micro task queue (promise1)

    1. Output: promise1 , a micro task is generated after then and added to the micro task queue, the current micro task queue (promise2)
    2. Execute then, output promise2
  3. Perform rendering operations and update the interface (knock on the blackboard to focus).
  4. Macro task: execute setTimeout

    1. Output: setTimeout

Promise execution

new Promise(..) is also a synchronous code and will be executed immediately. Only then the code executed asynchronously, which is a micro task.

console.log("script start");

setTimeout(function () {
  console.log("timeout1");
}, 10);

new Promise((resolve) => {
  console.log("promise1");
  resolve();
  setTimeout(() => console.log("timeout2"), 10);
}).then(function () {
  console.log("then1");
});

console.log("script end");

step analysis:

  • Current task queue: Micro task: [], Macro task: [ <script> ]
  1. Macro task:

    1. Output: script start
    2. Encounter timeout1, join the macro task
    3. When encountering Promise, output promise1 and directly resolve to add then to the micro task. When encountering timeout 2, add the macro task.
    4. Output script end
    5. The first execution of the macro task ends
  • Current task queue: micro task [then1], macro task [timeou1, timeout2]
  1. Micro task:

    1. Execute then1, output then1
    2. Micro task queue empty
  • Current task queue: micro task [], macro task [timeou1, timeout2]
  1. Macro task:

    1. Output timeout1
    2. Output timeout2
  • Current task queue: micro task [], macro task [timeou2]
  1. Micro task:

    1. Empty skip
  • Current task queue: micro task [], macro task [timeou2]
  1. Macro task:

    1. Output timeout2

async/await execution

Async and await are actually syntactic sugar for Generator and Promise.

The async function is no different from the normal function, it just means that there is an asynchronous operation method in this function and returns a Promise object

The translation is actually:

// async/await 写法
async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}
// Promise 写法
async function async1() {
  console.log("async1 start");
  Promise.resolve(async2()).then(() => console.log("async1 end"));
}

Look at the example:

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}
async function async2() {
  console.log("async2");
}
async1();
setTimeout(() => {
  console.log("timeout");
}, 0);
new Promise(function (resolve) {
  console.log("promise1");
  resolve();
}).then(function () {
  console.log("promise2");
});
console.log("script end");

step analysis:

  • Current task queue: Macro task: [ <script> ], Micro task: []
  1. Macro task:

    1. output: async1 start
    2. When encountering async2, outputs: async2 , and then (async1 end) is added to the micro task
    3. Encounter setTimeout, join the macro task.
    4. Encounter Promise, output: promise1 , directly resolve, add then (promise2) to the micro task
    5. output: script end
  • Current task queue: micro task [promise2, async1 end], macro task [timeout]
  1. Micro task:

    1. output: promise2
    2. promise2 out of the team
    3. output: async1 end
    4. async1 end dequeue
    5. Micro task queue empty
  • Current task queue: micro task [], macro task [timeout]
  1. Macro task:

    1. output: timeout
    2. timeout goes out of the team, the macro task is cleared

"Task Queue" is an event queue (can also be understood as a message queue). When an IO device completes a task, an event is added to the "Task Queue" to indicate that the related asynchronous task can enter the "execution stack" . The main thread reads the "task queue", which is to read what events are in it.

In addition to the events of the IO device, the events in the "task queue" also include some user-generated events (such as mouse clicks, page scrolling, etc.). As long as the callback function is specified, these events will enter the "task queue" and wait for the main thread to read.

The so-called "callback" (callback) is the code that will be hung up by the main thread. Asynchronous tasks must specify a callback function. When the main thread starts to execute the asynchronous task, the corresponding callback function is executed.

"Task Queue" is a first-in-first-out data structure, and the first events are read by the main thread first. The reading process of the main thread is basically automatic. As long as the execution stack is emptied, the first event on the "task queue" will automatically enter the main thread. However, due to the "timer" function mentioned later, the main thread must first check the execution time. Certain events can only return to the main thread after the specified time.

---- Execute immediately when there is no code in JavaScript, it is executed as soon as possible when the process is idle

setTimerout is not accurate

From the above, we already know that setTimeout is a macro task, which will be added to the macro task queue and executed in order, if there is one before it.

setTimeout() is to tell JavaScript how long to add the current task to the queue.

If the queue is empty, then the added code will be executed immediately; if the queue is not empty, then it will execute after the previous code is executed.

Look at the code:

const s = new Date().getSeconds();
console.log("script start");
new Promise((resolve) => {
  console.log("promise");
  resolve();
}).then(() => {
  console.log("then1");
  while (true) {
    if (new Date().getSeconds() - s >= 4) {
      console.log("while");
      break;
    }
  }
});
setTimeout(() => {
  console.log("timeout");
}, 2000);
console.log("script end");

Because then is a micro task, it will be executed before setTimeout, so although setTimeout is a macro task added after two seconds, because the while operation in then was delayed by 4s, it was delayed until 4s before execution. setTimeout.

So the order of output is: script start, promise, script end, then1.
Output after four seconds: while, timeout

Note: What should be added about setTimeout is that even if the main thread is empty, 0 milliseconds is actually not reachable. According to HTML standards, the minimum is 4 milliseconds. Interested students can find out for themselves.

<!-- ### Asynchronous rendering strategy-->
<!-- Take Vue as an example nextTick -->

to sum up

There is a small tip: from the specification, microtask is executed prior to task, so if there is logic that needs to be executed first, it will be executed earlier than task in the microtask queue.

Finally, remember that JavaScript is a single-threaded language, and asynchronous operations are placed in the event loop queue, waiting for the main execution stack to execute, and there is no dedicated asynchronous execution thread.

reference

Original from the : 1609e3514245a0 link to

九旬的博客
关注我,每周输出一篇前端技术文章, 博客地址:[链接]

关注我,每周输出一篇前端技术文章,

927 声望
1.2k 粉丝
0 条评论
推荐阅读
前端图片压缩方案
先通过 js 中 img 构造函数,实例化 img 对象,后将图片的路径给转移到中,再建立一个 canvas 画布,后对画布进行各方面的数值的设置。

九旬1阅读 212

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木150阅读 12.3k评论 10

正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青55阅读 7.8k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy46阅读 6k评论 12

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.2k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.3k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木44阅读 7.4k评论 6

关注我,每周输出一篇前端技术文章,

927 声望
1.2k 粉丝
宣传栏