IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 第 41 题:请描述一下 Javascript 事件循环机制? -> 正文阅读

[JavaScript知识库]第 41 题:请描述一下 Javascript 事件循环机制?

事件循环机制

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

  1. 执行一个宏任务(栈中没有就从事件队列中获取)

  2. 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中

  3. 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)

  4. 当前宏任务执行完毕,开始检查渲染,然后 GUI 线程接管渲染

  5. 渲染完毕后,JS 线程继续接管,开始下一个宏任务(从事件队列中获取)

流程图如下:

那么什么是宏任务和微任务呢?

宏任务

(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 的事件循环

#

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

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-07 10:43:35  更:2021-09-07 10:45:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:31:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码