JS内部事件机制之单线程原理


Posted in Javascript onJuly 02, 2018

任务队列

主线程:正在执行的代码,会生成函数调用栈。

  • macro-task(宏任务,新名:task)包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
  • micro-task(微任务,新名:jobs)包括: process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性,队列中只能有一个)

任务分类

同步任务,语句只按语句先后顺序执行,前面未执行完,不会执行后面语句。

异步任务,语句不在语句先后顺序上执行,执行到该代码时,加入到相应任务队列,延后执行。

单线程

主线程从 script (整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的 jobs。当所有可执行的 jobs 执行完毕之后。循环再次从 task 开始,找到其中一个任务队列执行完毕,然后再执行所有的 jobs,这样一直循环下去。

注意事项

  • setTimeout 最小间隔不能低于 4 毫秒,否则会自动增加。
  • DOM 的渲染每 16 毫秒执行一次,因为显示器是 60 Hz,16ms 刷新一次。
  • process.nextTick 任务会在 jobs 里单独维护一个队列,并且在其他 jobs 任务之前执行。
  • 冒泡事件会直接在子元素事件执行完成后,插入在主线程中。如果主线程不为空,那么会优先于 jobs 执行。

经典示例

示例详解:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

通过鼠标点击

<div class="outer">
 <div class="inner"></div>
</div>
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');
// Let's listen for attribute changes on the
// outer element
new MutationObserver(function() {
 console.log('mutate');
}).observe(outer, {
 attributes: true
});
// Here's a click listener…
function onClick() {
 console.log('click');
 setTimeout(function() {
  console.log('timeout');
 }, 0);
 Promise.resolve().then(function() {
  console.log('promise');
 });
 outer.setAttribute('data-random', Math.random());
}
// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);
// 输出结果
click
mutate
click
mutate
promise
promise
timeout
timeout

进阶--通过js执行

<div class="outer">
 <div class="inner"></div>
</div>
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');
// Let's listen for attribute changes on the
// outer element
new MutationObserver(function() {
 console.log('mutate');
}).observe(outer, {
 attributes: true
});
// Here's a click listener…
function onClick() {
 console.log('click');
 setTimeout(function() {
  console.log('timeout');
 }, 0);
 Promise.resolve().then(function() {
  console.log('promise');
 });
 outer.setAttribute('data-random', Math.random());
}
// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);
inner.click();
// 输出结果
click
click
mutate
promise
promise
timeout
timeout

由于点击事件是 js 执行的,inner 的 onClick 函数执行完成时,inner.click() 语句的作用域还没有退栈,主线程调用栈不是空的,导致 jobs 队列任务不会执行,mutate 和 promise 语句都未能在事件循环中执行到。从而执行了 outer 的 onClick 函数。outer 的 onClick 函数执行完成后,inner.click() 语句才退栈,继而执行 jobs 的任务。

只有一个 mutate 是由于 jobs 队列中,只能有一个 MutationObserver 任务,第二次创建时,前一个 MutationObserver 任务没有执行,顾不再创建。

总结

以上所述是小编给大家介绍的JS内部事件机制之单线程原理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jQuery中将函数赋值给变量的调用方法
Mar 23 Javascript
javascript当中的代码嗅探扩展原生对象和原型(prototype)
Jan 11 Javascript
js图片预加载示例
Apr 30 Javascript
JavaScript位移运算符(无符号) &gt;&gt;&gt; 三个大于号 的使用方法详解
Mar 31 Javascript
JS+CSS3制作炫酷的弹窗效果
Nov 08 Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
Feb 19 Javascript
如何理解Vue的.sync修饰符的使用
Aug 17 Javascript
node.js文件上传重命名以及移动位置的示例代码
Jan 19 Javascript
js构建二叉树进行数值数组的去重与优化详解
Mar 26 Javascript
JS中的函数与对象的创建方式
May 12 Javascript
解决微信小程序云开发中获取数据库的内容为空的方法
May 15 Javascript
微信小程序云开发之使用云数据库
May 17 Javascript
JS将网址url转化为JSON格式的方法
Jul 02 #Javascript
原生JS实现列表子元素顺序反转的方法分析
Jul 02 #Javascript
JS限制输入框输入的实现代码
Jul 02 #Javascript
webpack手动配置React开发环境的步骤
Jul 02 #Javascript
Angularjs中的$apply及优化使用详解
Jul 02 #Javascript
angularjs 的数据绑定实现原理
Jul 02 #Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
Jul 02 #Javascript
You might like
全国FM电台频率大全 - 19 广东省
2020/03/11 无线电
利用文件属性结合Session实现在线人数统计
2006/10/09 PHP
php中记录用户访问过的产品,在cookie记录产品id,id取得产品信息
2011/05/04 PHP
PHP+memcache实现消息队列案例分享
2014/05/21 PHP
ThinkPHP采用实现三级循环代码实例
2014/07/18 PHP
php实现的数组转xml案例分析
2019/09/28 PHP
PHP二维数组分页2种实现方法解析
2020/07/09 PHP
extjs之去除s.gif的影响
2010/12/25 Javascript
微信小程序 教程之事件
2016/10/18 Javascript
JS模拟实现ECMAScript5新增的数组方法
2017/03/20 Javascript
基于JavaScript实现焦点图轮播效果
2017/03/27 Javascript
ionic2打包android时gradle无法下载的解决方法
2017/04/05 Javascript
JS动态修改网页body的背景色实例代码
2017/10/07 Javascript
微信小程序App生命周期详解
2018/01/31 Javascript
jquery动态添加带有样式的HTML标签元素方法
2018/02/24 jQuery
vue-cli 目录结构详细讲解总结
2019/01/15 Javascript
IE浏览器下JS脚本提交表单后,不能自动提示问题解决方法
2019/06/04 Javascript
webpack4.0+vue2.0利用批处理生成前端单页或多页应用的方法
2019/06/28 Javascript
浅谈vue中$event理解和框架中在包含默认值外传参
2020/08/07 Javascript
Python 多进程和数据传递的理解
2017/10/09 Python
Python+threading模块对单个接口进行并发测试
2019/06/25 Python
python自动化测试之如何解析excel文件
2019/06/27 Python
python获取全国城市pm2.5、臭氧等空气质量过程解析
2019/10/12 Python
scrapy实践之翻页爬取的实现
2021/01/05 Python
Html5 video标签视频的最佳实践
2020/02/26 HTML / CSS
Spanx塑身衣官网:美国知名内衣品牌
2017/01/11 全球购物
应届生法律求职信
2013/10/22 职场文书
应届大学毕业生找工作的求职信范文
2013/11/29 职场文书
操行评语大全
2014/04/30 职场文书
甜品蛋糕店创业计划书
2014/09/21 职场文书
公务员考察材料
2014/12/23 职场文书
党员活动总结
2015/02/04 职场文书
实习生个人总结范文
2015/02/28 职场文书
2015教师个人师德工作总结
2015/10/23 职场文书
springboot+zookeeper实现分布式锁
2022/03/21 Java/Android
Win11 vmware不兼容怎么办?Win11与VMware虚拟机不兼容的解决方法
2023/01/09 数码科技