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 29 Javascript
node.js+Ajax实现获取HTTP服务器返回数据
Nov 26 Javascript
jQuery实现form表单基于ajax无刷新提交方法详解
Dec 08 Javascript
jQuery bt气泡实现悬停显示及移开隐藏功能的方法
Jul 12 Javascript
酷! 不同风格页面布局幻灯片特效js实现
Feb 19 Javascript
jQuery实现智能判断固定导航条或侧边栏的方法
Sep 04 Javascript
bootstrap读书笔记之CSS组件(上)
Oct 17 Javascript
微信小程序 图片上传实例详解
May 05 Javascript
Angular实现的敏感文字自动过滤与提示功能示例
Dec 29 Javascript
JS实现自定义弹窗功能
Aug 08 Javascript
JavaScript实用代码小技巧
Aug 23 Javascript
细说Vue组件的服务器端渲染的过程
May 30 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
杏林同学录(五)
2006/10/09 PHP
简单的PHP多图上传小程序代码
2011/07/17 PHP
php数组函数序列之in_array() - 查找数组中是否存在指定值
2011/11/07 PHP
PHP 之Section与Cookie使用总结
2012/09/14 PHP
php socket实现的聊天室代码分享
2014/08/16 PHP
ucenter中词语过滤原理分析
2016/07/13 PHP
windows环境下使用Composer安装ThinkPHP5
2018/05/18 PHP
在线编辑器的实现原理(兼容IE和FireFox)
2007/03/09 Javascript
JavaScript XML实现两级级联下拉列表
2008/11/10 Javascript
jquery下操作HTML控件的实现代码
2010/01/12 Javascript
JavaScript setTimeout和setInterval的使用方法 说明
2010/03/25 Javascript
javascript 精粹笔记
2010/05/09 Javascript
JQuery 应用 JQuery.groupTable.js
2010/12/15 Javascript
jquery isEmptyObject判断是否为空对象的函数
2011/02/14 Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
2013/11/14 Javascript
js中不同的height, top的区别对比
2015/09/24 Javascript
JS中call/apply、arguments、undefined/null方法详解
2016/02/15 Javascript
Bootstrap3制作自己的导航栏
2016/05/12 Javascript
Windows下使用Nodejs运行js的方法
2017/09/02 NodeJs
taro 实现购物车逻辑的实例代码
2020/06/05 Javascript
Element-ui el-tree新增和删除节点后如何刷新tree的实例
2020/08/31 Javascript
[03:12]TI9战队档案 - Virtus Pro
2019/08/20 DOTA
Python的设计模式编程入门指南
2015/04/02 Python
在Python中使用元类的教程
2015/04/28 Python
Python编程实现二叉树及七种遍历方法详解
2017/06/02 Python
基于python 微信小程序之获取已存在模板消息列表
2019/08/05 Python
Python实现线性判别分析(LDA)的MATLAB方式
2019/12/09 Python
Python 字符串处理特殊空格\xc2\xa0\t\n Non-breaking space
2020/02/23 Python
MCM英国官网:奢侈皮具制品
2017/04/18 全球购物
Qoo10台湾站:亚洲领先的在线市场
2018/05/15 全球购物
StubHub美国:购买或出售您的门票
2019/07/09 全球购物
2015年医生个人工作总结
2015/04/25 职场文书
2015教师个人德育工作总结
2015/07/22 职场文书
Python3.8官网文档之类的基础语法阅读
2021/09/04 Python
Spring依赖注入多种类型数据的示例代码
2022/03/31 Java/Android
Java实战之课程信息管理系统的实现
2022/04/01 Java/Android