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 风格的HTML文本转义
Jul 01 Javascript
JavaScript OOP面向对象介绍
Dec 02 Javascript
JavaScript中链式调用之研习
Apr 07 Javascript
ActiveX控件与Javascript之间的交互示例
Jun 04 Javascript
分享20个提升网站界面体验的jQuery插件
Dec 15 Javascript
Bootstrap学习笔记之css组件(3)
Jun 07 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
Aug 26 Javascript
jquery注册文本框获取焦点清空,失去焦点赋值的简单实例
Sep 08 Javascript
layui select获取自定义属性方法
Aug 15 Javascript
atom-design(Vue.js移动端组件库)手势组件使用教程
May 16 Javascript
vue动态禁用控件绑定disable的例子
Oct 28 Javascript
ES5新增数组的实现方法
May 12 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&amp;mysql(六)
2006/10/09 PHP
使用php的HTTP请求的库Requests实现美女图片墙
2015/02/22 PHP
PHP页面跳转操作实例分析(header方法)
2016/09/28 PHP
php实现根据身份证获取精准年龄
2020/02/26 PHP
javascript while语句和do while语句的区别分析
2007/12/08 Javascript
JQuery 学习笔记 选择器之六
2009/07/23 Javascript
javaScript中slice函数用法实例分析
2015/06/08 Javascript
js如何准确获取当前页面url网址信息
2020/09/13 Javascript
js实现精确到毫秒的倒计时效果
2016/08/05 Javascript
Jquery遍历select option和添加移除option的实现方法
2016/08/26 Javascript
Bootstrap table使用方法总结
2017/05/10 Javascript
Angularjs 实现动态添加控件功能
2017/05/25 Javascript
使用Bootstrap和Vue实现用户信息的编辑删除功能
2017/10/25 Javascript
layer实现关闭弹出层刷新父界面功能详解
2017/11/15 Javascript
js实现购物车功能
2018/06/12 Javascript
vue中vee validate表单校验的几种基本使用
2018/06/25 Javascript
JavaScript 链表定义与使用方法示例
2020/04/28 Javascript
基于javascript的无缝滚动动画实现2
2020/08/07 Javascript
详解vue3.0 的 Composition API 的一种使用方法
2020/10/26 Javascript
vue实现禁止浏览器记住密码功能的示例代码
2021/02/03 Vue.js
Python实现生成简单的Makefile文件代码示例
2015/03/10 Python
Python解析nginx日志文件
2015/05/11 Python
Python实现队列的方法
2015/05/26 Python
Python Json序列化与反序列化的示例
2018/01/31 Python
快速解决安装python没有scripts文件夹的问题
2018/04/03 Python
Python实现的查询mysql数据库并通过邮件发送信息功能
2018/05/17 Python
python实现录音小程序
2020/10/26 Python
python+selenium实现简历自动刷新的示例代码
2019/05/20 Python
pytorch 加载(.pth)格式的模型实例
2019/08/20 Python
C#如何调用Word并打开一个Word文档
2013/05/08 面试题
文员个人的求职信范文
2013/09/26 职场文书
思想专业自荐信范文
2013/12/25 职场文书
保安部任务及岗位职责
2014/02/25 职场文书
机关搬迁方案
2014/05/18 职场文书
幼儿园小班工作总结2015
2015/04/25 职场文书
初三英语教学反思
2016/02/15 职场文书