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 相关文章推荐
JavaScript实现禁止后退的方法
Dec 27 Javascript
js 表格隔行颜色
Dec 02 Javascript
jQuery 连续列表实现代码
Dec 21 Javascript
javascript不同类型数据之间的运算的转换方法
Feb 13 Javascript
ECMAScript6新增值比较函数Object.is
Jun 12 Javascript
JS两个数组比较,删除重复值的巧妙方法(推荐)
Jun 03 Javascript
js实现手机发送验证码功能
Mar 13 Javascript
JavaScript实现提交模式窗口后刷新父窗口数据的方法
Jun 16 Javascript
JS+HTML5实现图片在线预览功能
Jul 22 Javascript
浅谈webpack性能榨汁机(打包速度优化)
Jan 09 Javascript
JS实现简单打字测试
Jun 24 Javascript
结合axios对项目中的api请求进行封装操作
Sep 21 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
php中在PDO中使用事务(Transaction)
2011/05/14 PHP
thinkPHP实现的省市区三级联动功能示例
2017/05/05 PHP
解决laravel 表单提交-POST 异常的问题
2019/10/15 PHP
Yii框架布局文件的动态切换操作示例
2019/11/11 PHP
Javascript中Eval函数的使用说明
2008/10/11 Javascript
jquery1.4后 jqDrag 拖动 不可用
2010/02/06 Javascript
js中巧用cssText属性批量操作样式
2011/03/13 Javascript
jQuery中jqGrid分页实现代码
2011/11/04 Javascript
JavaSciprt中处理字符串之sup()方法的使用教程
2015/06/08 Javascript
JS实现很实用的对联广告代码(可自适应高度)
2015/09/18 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
2015/10/25 Javascript
JS for...in 遍历语句用法实例分析
2016/08/24 Javascript
微信小程序 Flex布局详解
2016/10/09 Javascript
12 款 JS 代码测试必备工具(翻译)
2016/12/13 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
2016/12/14 Javascript
jQuery快速高效制作网页交互特效
2017/02/24 Javascript
vue使用laydate时间插件的方法
2018/11/14 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
2020/03/23 Javascript
在Python中操作时间之mktime()方法的使用教程
2015/05/22 Python
Python 中 list 的各项操作技巧
2017/04/13 Python
python语言中with as的用法使用详解
2018/02/23 Python
Python 判断奇数偶数的方法
2018/12/20 Python
python加载自定义词典实例
2019/12/06 Python
将labelme格式数据转化为标准的coco数据集格式方式
2020/02/17 Python
经济学人订阅:The Economist
2018/07/19 全球购物
电气技术员岗位职责
2013/11/19 职场文书
2014年最新学习全国两会精神心得
2014/03/17 职场文书
大学生个人求职信例文
2014/07/07 职场文书
群众路线四风对照检查材料
2014/11/04 职场文书
具结保证书
2015/01/17 职场文书
开票员岗位职责
2015/02/12 职场文书
2015年社区宣传工作总结
2015/05/20 职场文书
初二英语教学反思
2016/02/15 职场文书
JavaScript 原型与原型链详情
2021/11/02 Javascript
SpringBoot整合Minio文件存储
2022/04/03 Java/Android
解决Oracle数据库用户密码过期
2022/05/11 Oracle