关于html:第-41-题请描述一下-Javascript-事件循环机制

41次阅读

共计 2397 个字符,预计需要花费 6 分钟才能阅读完成。

事件循环机制

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的工作解决是比较复杂的,但关键步骤如下:

  1. 执行一个宏工作(栈中没有就从事件队列中获取)
  2. 执行过程中如果遇到微工作,就将它增加到微工作的工作队列中
  3. 宏工作执行结束后,立刻执行以后微工作队列中的所有微工作(顺次执行)
  4. 以后宏工作执行结束,开始查看渲染,而后 GUI 线程接管渲染
  5. 渲染结束后,JS 线程持续接管,开始下一个宏工作(从事件队列中获取)

流程图如下:

<img src=”https://noxussj.top:3000/41/1.png”></img>

那么什么是宏工作和微工作呢?

宏工作

(macro)task(又称之为宏工作),能够了解是每次执行栈执行的代码就是一个宏工作(包含每次从事件队列中获取一个事件回调并放到执行栈中执行)

浏览器为了可能使得 JS 外部 (macro)task 与 DOM 工作可能有序的执行, 会在一个(macro)task 执行完结后,在下一个(macro)task 执行开始前,对页面进行从新渲染

(macro)task 次要蕴含:script(整体代码)、setTimeout、setInterval

微工作

microtask(又称为微工作),能够了解是在以后(macro) task 执行完结后立刻执行的工作。也就是说,在以后(macro)task 工作后,下一个(macro)task 之前,在渲染之前。

所以它的响应速度相比 setTimeout(setTimeout 是(macro)task)会更快,因为无需等渲染。也就是说,在某一个 macrotask 执行完后,就会将在它执行期间产生的所有 microtask 都执行结束(在渲染前)

microtask 次要蕴含:Promise.then、await 办法前面的代码属于.then(await 相当于一个 Promise)

栗子

async function async1() {console.log('A');
    await async2();
    console.log('B');
}
async function async2() {console.log('C');
}
console.log('D');
setTimeout(function() {console.log('E');
});
async1();
new Promise(function(resolve) {console.log('F');
    resolve();}).then(function() {console.log('G');
});
console.log('H');

首先咱们须要明确以下几件事件

工作队列次要包含以下 3 个,宏工作队列、微工作队列、执行栈

  1. 一开始执行栈,以及微工作队列为空,宏工作只有一个 script 代码块
  2. 执行栈为空时,就把下一个宏工作增加到执行栈中运行
  3. 开始运行宏工作 script
  4. 程序往下执行遇到了 console.log(‘D’),这个时候间接打印
    后果为:// D
  5. 而后持续往下执行遇到了 setTimeout,它属于宏工作所以先把它增加到宏工作队列中
    工作队列状态如下
    执行栈:script
    宏工作队列:setTimeout
    微工作队列:空
  6. 持续往下执行遇到了 async1()办法,运行该办法遇到了 console.log(‘A’),间接打印
    后果为:// D A
  7. 持续往下执行遇到了 async2()办法,运行该办法遇到了 console.log(‘C’),间接打印
    后果为:// D A C
  8. async2()办法内的程序都执行结束,回到上一层 async1()中,遇到 console.log(‘B’),它在 await async2() 的前面,所以属于异步并且增加到微工作队列中,而后回到最里面一层
    工作队列状态如下
    执行栈:script
    宏工作队列:setTimeout
    微工作队列:console.log(‘B’)
  9. 持续往下执行遇到了 new Promise(),该作用域内同步工作。执行作用域内办法,遇到了 console.log(‘F’),间接打印
    后果为:// D A C F
  10. 持续往下执行遇到了.then 属于异步,将 then 外部的代码增加到微工作队列中
    工作队列状态如下
    执行栈:script
    宏工作队列:setTimeout
    微工作队列:console.log(‘B’)、console.log(‘G’)
  11. 该 new Promise 办法执行结束,回到最初里面,遇到了 console.log(‘H’),间接打印
    后果为:// D A C F H
  12. 以后 script 代码块程序执行结束,也就是以后宏工作执行结束。在执行该宏工作的过程中,如果某个微工作曾经准备就绪好了会标记一个准备就绪的状态
  13. 将已就绪的微工作从微工作队列中增加到执行栈中
    工作队列状态如下
    执行栈:console.log(‘B’)、console.log(‘G’)
    宏工作队列:setTimeout
    微工作队列:空
  14. 开始运行执行栈的工作,按程序执行间接打印
    后果为:// D A C F H B G
    工作队列状态如下
    执行栈:空
    宏工作队列:setTimeout
    微工作队列:空
  15. 以后的执行栈为空,则把宏工作队列中的 setTimeout 增加到执行栈中运行
  16. setTimeout 中遇到了 console.log(‘E’)间接打印
    后果为:// D A C F H B G E
  17. 以后执行栈已执行结束,检测是否有微工作(没有),检测是否有宏工作(没有)。整个程序执行结束

此题留下了一个问题,假如遇到多个 setTimeout 提早执行的工夫不同时,该如何执行?

参考资料
从一道题浅说 JavaScript 的事件循环

文章的内容 / 灵感都从下方内容中借鉴

  • 【继续保护 / 更新 500+ 前端面试题 / 笔记】https://github.com/noxussj/In…
  • 【大数据可视化图表插件】https://www.npmjs.com/package…
  • 【利用 THREE.JS 实现 3D 城市建模(珠海市)】https://3d.noxussj.top/

正文完
 0