依据HTML标准再探Javascript事件循环及其与浏览器渲染的关系
Javascript的一些基础概念
JavaScript执行引擎在宿主环境中是单线程的,这意味着在同一时间内只能执行一个任务。在Javascript运行期间,引擎会创建和维护相应的堆(heap)和栈(stack)这两个数据结构;堆是存放数据变量的地方(这里很多前端er有个误区,认为js的引用类型存放在堆中,基础类型的变量是存放在栈中的),栈就是指执行栈。
对于浏览器来说,当它第一次加载你的<script>标签时,它默认进入了全局执行环境;如果你在全局代码中调用了一个函数,执行流就会进入到这个函数当中,创建一个新的执行环境并且把这个环境添加到执行栈的顶部。如果你在当前的函数中又调用了其他函数,同样的步骤会再来一次。浏览器始终执行当前在栈顶部的执行环境。一旦函数完成了当前的执行环境,它就会被弹出栈的顶部, 把控制权返回给栈中的下个执行环境:

上述任务都是同步执行的,这就会导致一个很常见的问题:如果执行了一段非常耗时的同步代码 例如请求数据、上传文件等,浏览器就会长时间无法渲染,页面阻塞不能响应交互。对于需要处理这类IO密集型任务的浏览器来说,Javascript当然是需要异步非阻塞机制的,这就是下面要讲的事件循环机制。
Event Loop
上面讲了执行栈中的所有任务从顶向下同步执行;但当遇到一些需要异步执行的任务,如ajax、setTimeout等时,会立即返回函数,然后将异步操作交给浏览器内核中的其他模块处理(如timer、network、DOM Binding模块等),接着主线程继续往下执行栈中的任务。当这些异步操作完成后如ajax接受完响应、setTimeout到达指定延时;这些任务的回调就会被放入到任务队列中。不同的异步任务的回调函数会被放入不同的任务队列之中。
在浏览器中是有两种不同类型的异步任务,国内的文章好像都是叫做“宏任务”和“微任务”,但在HTML标准(没错,事件循环这玩意是在HTML标准里的而不是ECMAScript标准定的)中并没有这么区分。在标准中,我们常说的“宏任务”就是指Task,常见的来源(Task Source)有:
- DOM操作
- UI交互
- 网络请求
- History APIs
- 定时器任务
- 。。。。。。
不同Task Source所产生的Task还会有自己的队列(Task Queue);当多个Task Queue都存在Task时,浏览器会自行调度决定先执行哪个;但同一Task Queue里的Task一定是按先进先出(FIFO)的顺序执行的。
后面出的新特性如Promise和MutationObserver,通常就是标准中的'Microtask'。与Task Queue不同的是,Microtask Queue只有一个。
当执行栈中所有任务都执行完了后,就会去Event Loop中去取出任务,放到执行栈中同步执行。Event Loop做了哪些事情呢,参考标准(Processing model),大概总结如下:
从Task Queue取出一个Task执行;至于如何选择哪个Task Queue(前面说过,Event Loop中会有多个Task Queue)取决于浏览器实现方。
依次执行Microtask Queue中的所有Microtask。注意,在本轮循环中新增的Microtask也会在此执行完。
设置变量now的值。后续如果执行
window.requestAnimationFrame或Intersection Observer的话,传入回调函数中的时间戳就是这个变量now。更新渲染
浏览器会根据刷新频率和页面状态等因素来决定是否要跳过该次渲染更新。例如 当浏览器试图达到60Hz的刷新频率时,会让更新渲染的次数在一秒内最多达到60次(16.6ms一次),但如果浏览器发现页面无法稳定维持该帧率的话,就会降到30Hz,那么更新渲染的几率就被降低了一半;或者当前页面的可见性为否时,浏览器可以将该页面降低至每秒4次甚至更低的更新渲染次数;又或者当前的渲染不会有可见的差异等。
如果确认需要更新渲染:
触发
resize、scroll和fullscreen等事件的处理函数并传入刚刚前面设置的now作为时间戳;并不是说到这里才会更新视图,窗口大小和滚动是会马上更新的,只是需要在一次事件循环中走到这一步时,才会触发这些事件的分发执行帧动画回调,传入刚刚前面设置的now作为时间戳;
window.requestAnimationFrame就是在此时执行的执行
Intersection Observer API的回调渲染页面内容并提交
每当一轮循环结束后,会判断Task Queue和Microtask Queue是否为空。都为空的话则再根据空闲周期算法决定是否执行
requestIdleCallback回调。

依据HTML标准再探Javascript事件循环及其与浏览器渲染的关系的更多相关文章
- c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)
c#封装DBHelper类 public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...
- 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)
JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...
- JavaScript 事件循环
JavaScript 事件循环 事件循环 任务队列 async/await 又是如何处理的呢 ? 定时器问题 阻塞还是非阻塞 实际应用案例 拆分 CPU 过载任务 进度指示 在事件之后做一些事情 事件 ...
- Javascript:再论Javascript的单线程机制 之 DOM渲染时机
Javascript:再论Javascript的单线程机制 之 DOM渲染时机 背景 Javascript是单线程事件驱动的,所有能看到的Javascript代码都是在一个线程执行,定时器回调和AJA ...
- 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果
学习笔记---Javascript事件Event.IE浏览器下的拖拽效果 1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...
- 深入理解 JavaScript 事件循环(二)— task and microtask
引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...
- [译] 深入理解 JavaScript 事件循环(二)— task and microtask
引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...
- JavaScript 事件循环及异步原理(完全指北)
引言 最近面试被问到,JS 既然是单线程的,为什么可以执行异步操作? 当时脑子蒙了,思维一直被困在 单线程 这个问题上,一直在思考单线程为什么可以额外运行任务,其实在我很早以前写的博客里面有写相关的内 ...
- 深入浅出Javascript事件循环机制
一.JS单线程.异步.同步概念 众所周知,JS是单线程(如果一个线程删DOM,一个线程增DOM,浏览器傻逼了-所以只能单着了),虽然有webworker酱紫的多线程出现,但也是在主线程的控制下.web ...
- 深入理解 JavaScript 事件循环(一)— event loop
引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...
随机推荐
- 在Flutter中使用SetState无效?可能是忽略了这个!
这次是Flutter开发技术分享,解决的问题点来自本人实际的开发经历. 首先描述一下问题:在某个组件中调用setState()方法更新该组件状态,结果是无法做到更新效果,组件仍然维持原状. 下面我们用 ...
- django DRF
博客目录 web应用模式 api接口 接口测试工具postman restful规范 drf安装 序列化和反序列化 CBV源码分析 drf之APIView分析 drf之Request对象分析 drf- ...
- 深挖 Python 元组 pt.2
哈喽大家好,我是咸鱼 在<深挖 Python 元组 pt.1>中我们了解 Python 元组的一些概念(索引和切片等),以及如何创建元组,最重要的是我们还介绍了元组的不可变特性 那么今天我 ...
- POJ 1742 Coins(多重背包的可行性问题)
Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar. ...
- P1525 关押罪犯 (并查集 / 二分图)| 二分图伪码
原题链接:https://www.luogu.com.cn/problem/P1525 题目概括: 给你m对关系,每对关系分别涉及到x,y两人,矛盾值为w 请你判断分配x和y到两个集合中,能否避免冲突 ...
- 面试通过,拿到offer了,不去了会怎么样?
接受了offer但不去,其实没啥事,但这属于诚信问题. 这里有个概念,给了offer但不接受,这没事. 给了offer,也接受了,但在入职前一周(或在其它约定的时间范围内)说不去,同时姿态放低些打招呼 ...
- 数字孪生智慧物流之 Web GIS 地图应用
前言 随着数字经济时代的来临,新一轮全球化进程速度加快,在大数据.人工智能.物联网等高新技术深度融合下,加快催化智慧物流发展,引领物流行业划入全新时代. 从物流运输到货物分拣再到站点配送,图扑软件数据 ...
- 从运维域看 Serverless 真的就是万能银弹吗?
作者说 在开始本篇内容前我想与各位开发者达成几个共识. 第一个共识,软件工程没有银弹, Serverless 也不是银弹,它并不是解决所有问题的万能公式. 第二个共识,Serverless 能 ...
- 《3D编程模式》写书-第4次记录
大家好,这段时间我完成了"再看设计原则"的初稿,包括了设计基础.单一职责原则.依赖倒置原则.接口隔离原则.合成复用原则.最少知识原则.开闭原则 目前我已经完成了所有的初稿,后面会进 ...
- Vue3使用vue-video-player组件
1.安装依赖(亲测5.0.1版本可用,最新版本会找不到'vue-video-player/src/custom-theme.css'这个样式) yarn add vue-video-player@5 ...