当前位置: 首页 > news >正文

对浏览器事件循环机制的理解

目录

      • 事件循环宏观理解
      • 事件循环异步任务细分宏任务与微任务后的理解
      • 结合流程图与代码理解览器事件循环

首先来介绍一些谷歌浏览器的进程与线程。

谷歌浏览器包含五个进程:浏览器主进程、渲染进程、GPU进程、网络进程、插件进程。

其中最重要的渲染进程包含五个线程:渲染线程、js引擎线程、事件触发回调线程、定时器触发线程、http请求线程。

由于js是单线程,所以在js引擎线程外才会分出事件回调、定时器、http请求三个线程用于执行对应的异步任务,由js引擎线程来执行同步任务以及异步结束后的任务。

事件循环宏观理解

js执行同步任务和异步任务的流程:首先js引擎线程(主线程)在执行js任务时会有一个执行栈,js代码从上到下依次执行时遇到的同步任务会推入执行栈中执行,遇到异步任务会先在主线程执行一点,然后会推入对应的线程执行异步代码,在主线程之外存在一个任务队列,所有异步任务在对应线程执行完后会进入任务队列处于等待状态,在主线程的执行栈执行完后会读取任务队列,然后取出任务队列的第一个事件执行,这个事件对应的异步任务结束等待状态,进入执行栈,开始执行。然后主线程会一直重复上面的操作(执行执行栈中所有同步任务,然后再执行任务队列的第一个事件,一直重复

事件循环异步任务细分宏任务与微任务后的理解

异步任务又分为宏任务微任务(也就是任务队列分为宏任务队列和微任务队列):

  • 宏任务:整体代码(全局)、setTimeout 和 setInterval、setImmediate(Node.js 中)、I/O 操作(鼠标事件、键盘事件、网络事件等)、UI 渲染
  • 微任务:Promise.then(Promise 的回调)、process.nextTick(Node.js中)、MutationObserver(DOM变动观察)

宏任务与微任务的区别在于任务队列中事件的执行优先级,宏任务的优先级要高于微任务。

在一个事件循环中,异步事件返回结果后会被放到任务队列中。然而,根据这个异步事件的类型,这个事件实际上会放到对应的宏任务队列或者微任务队列中去。进入整体代码(宏任务)后,开始首次事件循环,当执行栈清空后(也就是同步任务执行完,开始进入任务队列执行异步任务事件时),事件循环机制会优先检测微任务队列中的事件并推至主线程执行,当微任务队列清空后,才会去检测宏任务队列中的事件,再将宏任务队列的第一个事件推至主线程中执行,然后开始第二次事件循环,执行栈清空所有同步任务,事件循环机制又会检测微任务队列,再去宏任务队列,如此反复循环。

我们只需记住当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行

结合流程图与代码理解览器事件循环

  • 第一个 <script> 标签的代码是第一个宏任务(这里可以把同步任务理解为第一个宏任务)
  • process.nextTick 优先级高于 Promise.then

图解:

在这里插入图片描述

事件循环完整流程:执行栈执行所有同步任务(也可以看作是一次宏任务)->进入微任务队列执行所有微任务事件->进入宏任务队列执行排在第一位的事件;然后再以次重复下去形成浏览器的事件循环

结合代码理解:

    // 同步任务1console.log(1);setTimeout(() => {// 宏任务console.log(2);}, 0);let promise = new Promise((res) => {// 同步任务2console.log(3);resolve();}).then((res) => {// 微任务1console.log(4);}).then((res) => {// 微任务2console.log(5);});// 同步任务3console.log(6);// 1 3 6 4 5 2// 执行栈先执行所有同步任务,再进入微任务队列执行所有微任务,最后再执行宏任务队列的第一个

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Redis 篇-深入了解基于 Redis 实现消息队列(比较基于 List 实现消息队列、基于 PubSub 发布订阅模型之间的区别)
  • JDBC简介与应用:Java数据库连接的核心概念和技术
  • 【Redis】Redis 典型应用 - 缓存 (Cache) 原理与策略
  • BuripSuiteProfessional 抓取HTTPS配置
  • Java实现简易计算器功能(idea)
  • day5 QT
  • 多级缓存的设计与实现
  • C语言代码练习(第十八天)
  • ​如何使用QGIS制作三维建筑
  • 一张图告诉你常见的响应状态码!200报错400 404 500都是什么意思??
  • 光耦合器的工作原理和故障诊断
  • 25. MyBatis中的RowBounds是什么?如何实现内存分页?
  • KAN 学习 Day4 —— MultKAN 正向传播代码解读及测试
  • 【RabbitMQ】概述
  • 骨传导耳机哪个品牌比较好?盘点五款闭眼入都不踩雷的优质骨传导耳机!
  • $translatePartialLoader加载失败及解决方式
  • 《剑指offer》分解让复杂问题更简单
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • gcc介绍及安装
  • Git初体验
  • JavaScript实现分页效果
  • jdbc就是这么简单
  • JS基础之数据类型、对象、原型、原型链、继承
  • Python爬虫--- 1.3 BS4库的解析器
  • spring + angular 实现导出excel
  • ucore操作系统实验笔记 - 重新理解中断
  • Vue 动态创建 component
  • 闭包--闭包作用之保存(一)
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 对JS继承的一点思考
  • 构建二叉树进行数值数组的去重及优化
  • 学习笔记TF060:图像语音结合,看图说话
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • PostgreSQL之连接数修改
  • 大数据全解:定义、价值及挑战
  • ​​​​​​​​​​​​​​Γ函数
  • ​决定德拉瓦州地区版图的关键历史事件
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #ifdef 的技巧用法
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #QT(一种朴素的计算器实现方法)
  • (12)目标检测_SSD基于pytorch搭建代码
  • (175)FPGA门控时钟技术
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (十七)Flink 容错机制
  • (算法二)滑动窗口
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。