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库的最佳方法详细说明及实现代码
Dec 28 Javascript
关于extjs4如何获取grid修改后的数据的问题
Aug 07 Javascript
js中跨域方法原理详解
Jul 19 Javascript
AngularJS 中的指令实践开发指南(一)
Mar 20 Javascript
浅析jquery数组删除指定元素的方法:grep()
May 19 Javascript
仿Angular Bootstrap TimePicker创建分钟数-秒数的输入控件
Jul 01 Javascript
JS常用函数和常用技巧小结
Oct 15 Javascript
JavaScript中立即执行函数实例详解
Nov 04 Javascript
axios实现简单文件上传功能
Sep 25 Javascript
微信小程序如何获取地址
Dec 24 Javascript
关于小程序优化的一些建议(小结)
Dec 10 Javascript
jquery实现点击左右按钮切换图片
Jan 27 jQuery
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
mysql下创建字段并设置主键的php代码
2010/05/16 PHP
php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法
2013/09/28 PHP
php中AES加密解密的例子小结
2014/02/18 PHP
支持中文的PHP按字符串长度分割成数组代码
2015/05/17 PHP
云网广告中的代码,提示出错,大家找找
2006/11/21 Javascript
JavaScript中的稀疏数组与密集数组[译]
2012/09/17 Javascript
js解析与序列化json数据(一)json.stringify()的基本用法
2013/02/01 Javascript
js使用正则实现ReplaceAll全部替换的方法
2014/08/22 Javascript
跟我学习javascript的垃圾回收机制与内存管理
2015/11/23 Javascript
jQuery实现模仿微博下拉滚动条加载数据效果
2015/12/25 Javascript
莱鸟介绍javascript onclick事件
2016/01/06 Javascript
AngularJS通过$location获取及改变当前页面的URL
2016/09/23 Javascript
js HTML5多媒体影音播放
2016/10/17 Javascript
bootstrap 模态框(modal)实现水平垂直居中显示
2017/01/23 Javascript
详解VueJs前后端分离跨域问题
2017/05/24 Javascript
node.js操作mysql简单实例
2017/05/25 Javascript
深入浅析var,let,const的异同点
2018/08/07 Javascript
Nuxt.js之自动路由原理的实现方法
2018/11/21 Javascript
整理 node-sass 安装失败的原因及解决办法(小结)
2020/02/19 Javascript
vue中如何自定义右键菜单详解
2020/12/08 Vue.js
详解python时间模块中的datetime模块
2016/01/13 Python
Python根据指定日期计算后n天,前n天是哪一天的方法
2018/05/29 Python
python使用PIL和matplotlib获取图片像素点并合并解析
2019/09/10 Python
python 实现批量替换文本中的某部分内容
2019/12/13 Python
Python获取指定网段正在使用的IP
2020/12/14 Python
HTML5等待加载动画效果
2017/07/27 HTML / CSS
详解canvas多边形(蜘蛛图)的画法示例
2018/01/29 HTML / CSS
纽约家具、家居装饰和地毯店:ABC Carpet & Home
2017/06/21 全球购物
Under Armour安德玛荷兰官网:美国高端运动科技品牌
2019/07/10 全球购物
文员个人的求职信范文
2013/09/26 职场文书
知识竞赛活动方案
2014/02/18 职场文书
出生证明公证书
2014/04/09 职场文书
环境科学专业求职信
2014/08/04 职场文书
2016年“我们的节日·重阳节”主题活动总结
2016/04/01 职场文书
健身房被搭讪?用python写了个小米计时器助人为乐
2021/06/08 Python
Python下载商品数据并连接数据库且保存数据
2022/03/31 Python