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的商品展示放大镜
Aug 07 Javascript
js全屏显示显示代码的三种方法
Nov 11 Javascript
一个简单的动态加载js和css的jquery代码
Sep 01 Javascript
js实现图片和链接文字同步切换特效的方法
Feb 20 Javascript
Javascript中的getUTCDay()方法使用详解
Jun 10 Javascript
JavaScript中的acos()方法使用详解
Jun 14 Javascript
学习javascript文件加载优化
Feb 19 Javascript
BootStrap modal模态弹窗使用小结
Oct 26 Javascript
jquery点赞功能实现代码 点个赞吧!
May 29 jQuery
详解通过JSON数据使用VUE.JS
May 26 Javascript
Vue.js对象转换实例
Jun 07 Javascript
vue页面切换到滚动页面显示顶部的实例
Mar 13 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
图解上海144收音机
2021/03/02 无线电
浅谈PHP正则表达式中修饰符/i, /is, /s, /isU
2014/10/21 PHP
一个经典的PHP文件上传类分享
2014/11/18 PHP
php生成随机颜色方法汇总
2014/12/03 PHP
PHP中使用php://input处理相同name值的表单数据
2015/02/03 PHP
php实现ip白名单黑名单功能
2015/03/12 PHP
ThinkPHP 5.x远程命令执行漏洞复现
2019/09/23 PHP
javascript 文档的编码问题解决
2009/03/01 Javascript
Jquery 组合form元素为json格式,asp.net反序列化
2009/07/09 Javascript
jQuery-Tools-overlay 使用介绍
2012/07/14 Javascript
JavaScript中的原型prototype完全解析
2016/05/10 Javascript
JS创建事件的三种方法(实例代码)
2016/05/12 Javascript
JS实现图片局部放大或缩小的方法
2016/08/20 Javascript
浅析Javascript ES6新增值比较函数Object.is
2016/08/24 Javascript
js a标签点击事件
2017/03/30 Javascript
使用jQuery 操作table 完成单元格合并的实例
2017/12/27 jQuery
vue实现a标签点击高亮方法
2018/03/17 Javascript
详解webpack4多入口、多页面项目构建案例
2018/05/25 Javascript
使用typescript构建Vue应用的实现
2019/08/26 Javascript
javascript实现贪吃蛇小游戏
2020/07/28 Javascript
Vue Router中应用中间件的方法
2020/08/06 Javascript
python中实现php的var_dump函数功能
2015/01/21 Python
python实现下载指定网址所有图片的方法
2015/08/08 Python
Python数据类型详解(四)字典:dict
2016/05/12 Python
Python 常用string函数详解
2016/05/30 Python
Python 使用PIL中的resize进行缩放的实例讲解
2018/08/03 Python
使用python制作游戏下载进度条的代码(程序说明见注释)
2019/10/24 Python
python 获取剪切板内容的两种方法
2020/11/28 Python
Python实现随机爬山算法
2021/01/29 Python
网页布局中CSS样式无效的十个重要原因详解
2017/08/10 HTML / CSS
银行会计业务的个人自我评价
2013/11/02 职场文书
2014年文学毕业生自我鉴定
2014/04/23 职场文书
小学生志愿者活动方案
2014/08/23 职场文书
2014乡镇干部纪律作风整顿思想汇报
2014/09/13 职场文书
一次线上mongo慢查询问题排查处理记录
2022/03/18 MongoDB
MySQL创建管理HASH分区
2022/04/13 MySQL