当前位置:   article > 正文

浏览器事件循环机制、宏任务和微任务_浏览器宏任务

浏览器宏任务

浏览器的事件循环机制(重要)

图片

image-20230608154453933

执行顺序如下:

  • 同步任务:进入主线程后,立即执行。

  • 异步任务:会先进入 Event Table;等时间到了之后,再进入 任务队列 (Event Queue)排队(排队是因为同一时间,JS 只能执行一个任务),先进先出。比如说,setTimeout(()=> {}, 1000)这种定时器任务,需要等一秒之后再进入 Event Queue。

  • 当主线程的任务执行完毕之后,此时主线程处于空闲状态,于是会去读取 Event Queue 中的任务队列,如果有任务,则进入到主线程去执行。

Node.js 事件循环机制

浏览器的 EventLoop 依据的是 HTML5 规范。而 Node.js 的 EventLoop 是由Node.js底层的 libuv 规定的。 libuv是一个专注于异步IO的跨平台库。

Node.js的事件循环中,有六个队列。其中,微任务有两个队列,宏任务有四个队列。

一、微任务队列:

  • 顺序1:next tick queue。比如:process.nextTick

  • 顺序2:other queue。比如:Promise的then回调、queueMicrotask

二、宏任务队列:

  • 顺序3:timer queue。比如:setTimeout、setInterval

  • 顺序4:poll queue。比如:IO事件

  • 顺序5:check queue。比如:setImmediate

  • 顺序6:close queue。比如:close事件

参考链接:

  • 【荐】浏览器及nodeJS中的EventLoop事件循环机制:https://www.cnblogs.com/weiyongchao/p/13766429.html

  • 浏览器和Node 事件循环的区别:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/26

宏任务和微任务

JS中的任务分为同步任务、异步任务。

JS中的异步任务分为宏任务(macrotask)、微任务(microtask)。在早期,异步任务中只有宏任务,没有微任务。后来的语言标准中,推出了“微任务”,因为希望微任务能够尽早执行

宏任务、微任务分类

事件循环的队列中,有两个队列。

1、宏任务队列,包含这些任务:

  • ajax 网络请求

  • setTimeout、setInterval

  • DOM事件

  • UI渲染

  • I/O文件读写操作。

2、微任务队列,包含这些任务:

  • Promise的then回调

  • Mutation Observer API:监听DOM节点变化。

  • queueMicrotask():可直接将某个任务加入到微任务队列中。

在执行一个 Promise 对象时,当走完 resolve() 进入 fulfilled状态后,会立刻把 .then()里面的代码加入到微任务队列当中。

任务的执行顺序

JS中的任务执行顺序:同步任务 --> 微任务 --> 宏任务

在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查询微任务队列中是否还有任务需要执行

  • 当前宏任务执行之前,必须要保证微任务队列是空的。

  • 如果微任务队列不为空,那就优先执行微任务队列中的任务。

任务执行顺序的面试题

实际开发中,基本不会出现下面这些题目,因为很多时候我们无法精准控制异步任务的执行顺序。但是它们在面试中出现的频率特别高,因为熟悉这些思维训练,有利于考察我们对JS单线程、事件循环机制、宏任务和微任务等原理的掌握程度。

题 1:宏任务和微任务的执行顺序

  1. setTimeout(() => {
  2.   // 宏任务
  3.   console.log('setTimeout');
  4. }, 0);
  5.  
  6. new Promise((resolve, reject) => {
  7.   resolve();
  8.   console.log('promise1'); // 同步任务
  9. }).then((res) => {
  10.   // 微任务
  11.   console.log('promise then');
  12. });
  13.  
  14. console.log('同步任务'); // 同步任务

打印结果:

  1. promise1
  2. 同步任务
  3. promise then
  4. setTimeout

上方代码执行的顺序依次是:同步任务 --> 微任务 --> 宏任务

题 2:在宏任务中嵌套了微任务

  1. new Promise((resolve, reject) => {
  2.   setTimeout(() => {
  3.     resolve();
  4.     console.log('setTimeout'); // 宏任务
  5.   }, 0);
  6.   console.log('promise1');
  7. }).then((res) => {
  8.   // 微任务
  9.   console.log('promise then');
  10. });
  11.  
  12. console.log('同步任务');

打印结果:

  1. promise1
  2. 同步任务
  3. setTimeout
  4. promise then

上方代码解释:在执行宏任务的过程中,创建了一个微任务。但是需要先把当前这个宏任务执行完,再去创建并执行微任务。

题3:综合题

  1. console.log("script start")
  2.  
  3. setTimeout(() => {
  4.   console.log("setTimeout1");
  5.   new Promise(resolve => {
  6.     resolve();
  7.   }).then(() => {
  8.     new Promise(resolve => {
  9.       resolve();
  10.     }).then(() => {
  11.       console.log("then1");
  12.     });
  13.     console.log("then2");
  14.   });
  15. });
  16.  
  17. new Promise(resolve => {
  18.   // 下面这两行代码,即便调换顺序,也不影响打印结果
  19.   console.log("promise1");
  20.   resolve();
  21. }).then(() => {
  22.   console.log("then3");
  23. });
  24.  
  25. setTimeout(() => {
  26.   console.log("setTimeout2");
  27. });
  28.  
  29. console.log('同步代码');
  30.  
  31. queueMicrotask(() => {
  32.   console.log("queueMicrotask")
  33. });
  34.  
  35. new Promise(resolve => {
  36.   resolve();
  37. }).then(() => {
  38.   console.log("then4");
  39. });
  40.  
  41. console.log("script end");

打印结果:

  1. // 第一次循环
  2. script start
  3. promise1
  4. 同步代码
  5. script end
  6.  
  7. // 第二次循环
  8. then3
  9. queueMicrotask
  10. then4
  11.  
  12. // 第三次循环
  13. setTimeout1
  14. then2
  15. then1
  16.  
  17. // 第四次循环
  18. setTimeout2

题4:async await 题目

代码举例:

  1. console.log('script start')
  2.  
  3. async function async2() {
  4.   console.log('async2')
  5. }
  6.  
  7. async function async1() {
  8.   console.log('async1 start')
  9.   await async2();
  10.   console.log('async1 end')
  11. }
  12.  
  13. setTimeout(() => {
  14.   console.log('setTimeout')
  15. }, 0)
  16.  
  17. async1();
  18.  
  19. new Promise(resolve => {
  20.   console.log('promise1')
  21.   resolve();
  22. }).then(function () {
  23.   console.log('then1')
  24. })
  25.  
  26. console.log('script end');

打印结果:

  1. script start
  2. async1 start
  3. async2
  4. promise1
  5. script end
  6.  
  7. async1 end
  8. then1
  9.  
  10. setTimeout

原文地址:浏览器事件循环机制、宏任务和微任务 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号