javascript中的event loop事件循环详解


Posted in Javascript onDecember 14, 2018

前言

javascript是单线程的语言,也就是说,同一个时间只能做一件事。而这个单线程的特性,与它的用途有关,作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质

这是今天一个朋友发给我的一个面试题,

感觉还挺有意思的,

写个博客以供分享

先看看这个面试题目:

观察下面的代码,写出输出结果

console.log('0')
setTimeout(function () {
 console.log('1');
});

new Promise(function(resolve,reject){
 console.log('2')
 resolve(3)
}).then(function(val){
 console.log(val)
})
console.log(4)

输出结果: “0” “2” 4 3 “1”

今天主要是分析为什么输出结果是这样的?这就和 javascript 的执行机制密切相关了.

Event Queue 和 Event Loop

javascript 是一门单线程的语言, 这就意味着在执行代码的时候, 都只有一个主线程来处理所有的任务.

我们都知道 javascript 包括同步代码和异步代码, 那么 javascript 是怎么处理这两种情况的呢?

  • 同步和异步任务分别进入不同的执行 场所, 同步的进入主线程,异步的进入 Event Table 并注册函数
  • 当指定的事情完成时, Event Table 会将这个函数(回调函数)移入 Event Queue
  • 主线程内的任务执行完毕为空, 会去 Event Queue 读取对应的函数,进入主线程执行
  • 上述过程会不断重复, 也就是常说的 Event Loop(事件循环)

这里我们引进了 Event Queue 事件队列这一概念. 所有异步操作的回调都会进入到这里. 然后等到主线程空闲, 就会从这里调取回调执行.

setTimeout

setTimeout 相信大家都有使用过, 可以延时执行并且是异步执行的.

但是有时候我们得到的结果往往是代码实际执行的时间比我们想要延时执行的时间要久。这又是为什么呢?

这就和我们之前所说的 Event Loop 有关了, 我们可以来具体看下 setTimeout 的执行步骤:

setTimeout(function () {
asyncFn()
}, 1000);

syncFn()
  • asyncFn 将异步执行函数放在 Event Table, 并且开始计时
  • 开始执行 syncFn, 但是 syncFn 可能需要处理的内容很多, 执行时间超过 1 秒, 但是计时还在继续
  • 计时到达 1 秒, setTimeout 延时完成, asyncFn 进入 Event Queue 事件队列, 但是主线程还在执行, 所以只能等待
  • syncFn 执行完成, 此时 asyncFn 从事件队列中进入主线程执行

所以有时候会出现代码实际执行时间比延时时间长的情况。

宏任务和微任务

之前我们说过异步任务会进入到事件队列中, 不同类型的任务会进入到不同的队列中, 比如宏任务会进入到宏任务队列中, 微任务会进入到微任务队列中.

我们只要记住 当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行

这时候我们就可以解释一开始的代码执行结果了:

  • 主线程执行按顺序代码
  • 遇到 setTimeout, 回调进入到宏任务队列上
  • 遇到 Promise, 立即执行, then 函数进入到微任务队列
  • 同步代码执行结束, 主线程检查是否存在微任务, 发现 then, 执行
  • 微任务执行完毕, 再去查找宏任务 setTimeout, 执行
  • setTimeout 执行结束, 检查是否存在微任务, 不存在, 结束.

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jquery 插件开发 extjs中的extend用法小结
Jan 04 Javascript
JavaScript:Date类型全面解析
May 19 Javascript
Vue.js表单控件实践
Oct 27 Javascript
jQuery webuploader分片上传大文件
Nov 07 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
Nov 18 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
Aug 11 Javascript
angular2 ng2 @input和@output理解及示例
Oct 10 Javascript
JS开发中基本数据类型具体有哪几种
Oct 19 Javascript
浅谈Vue CLI 3结合Lerna进行UI框架设计
Apr 14 Javascript
js使用cookie实现记住用户名功能示例
Jun 13 Javascript
Node.js API详解之 querystring用法实例分析
Apr 29 Javascript
React配置子路由的实现
Jun 03 Javascript
如何在Vue中使用CleaveJS格式化你的输入内容
Dec 14 #Javascript
webpack配置proxyTable时pathRewrite无效的解决方法
Dec 13 #Javascript
node.js学习笔记之koa框架和简单爬虫练习
Dec 13 #Javascript
浅谈vuex actions和mutation的异曲同工
Dec 13 #Javascript
webpack3里使用uglifyjs压缩js时打包报错的解决
Dec 13 #Javascript
javascript对HTML字符转义与反转义
Dec 13 #Javascript
Web安全之XSS攻击与防御小结
Dec 13 #Javascript
You might like
别人整理的服务器变量:$_SERVER
2006/10/20 PHP
PHP遍历并打印指定目录下所有文件实例
2014/02/10 PHP
ThinkPHP水印功能实现修复PNG透明水印并增加JPEG图片质量可调整
2014/11/05 PHP
PHP实现将HTML5中Canvas图像保存到服务器的方法
2014/11/28 PHP
php强制更新图片缓存的方法
2015/02/11 PHP
IE中jscript/javascript的条件编译
2006/09/07 Javascript
jQuery EasyUI API 中文文档 - TreeGrid 树表格使用介绍
2011/11/21 Javascript
jquery easyui滚动条部分设置介绍
2013/09/12 Javascript
JavaScript避免内存泄露及内存管理技巧
2014/09/05 Javascript
JQUERY实现网页右下角固定位置展开关闭特效的方法
2015/07/27 Javascript
jQuery代码实现发展历程时间轴特效
2015/07/30 Javascript
javascript伸缩菜单栏实现代码分享
2015/11/12 Javascript
node.js连接mongoDB数据库 快速搭建自己的web服务
2016/04/17 Javascript
JS递归遍历对象获得Value值方法技巧
2016/06/14 Javascript
vue小图标favicon不显示的解决方案
2017/09/19 Javascript
vue2.0s中eventBus实现兄弟组件通信的示例代码
2017/10/25 Javascript
vue+element UI实现树形表格带复选框的示例代码
2019/04/16 Javascript
JavaScript如何获取一个元素的样式信息
2019/07/29 Javascript
NodeJS实现一个聊天室功能
2019/11/25 NodeJs
Python 加密的实例详解
2017/10/09 Python
使用Anaconda3建立虚拟独立的python2.7环境方法
2018/06/11 Python
python实现在图片上画特定大小角度矩形框
2018/10/24 Python
python实现向微信用户发送每日一句 python实现微信聊天机器人
2019/03/27 Python
使用pandas读取文件的实现
2019/07/31 Python
将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例
2020/01/04 Python
详解matplotlib绘图样式(style)初探
2021/02/03 Python
Timberland德国官网:靴子、鞋子、衣服、夹克及配件
2019/12/10 全球购物
商务英语专业自荐信
2013/10/14 职场文书
学生党员思想汇报
2013/12/28 职场文书
批评与自我批评范文
2014/10/15 职场文书
开展党的群众路线教育实践活动工作总结
2014/11/05 职场文书
成本会计实训报告
2014/11/05 职场文书
2014年卫生保健工作总结
2014/12/08 职场文书
2016大学生就业指导课心得体会
2016/01/15 职场文书
Mysql中有关Datetime和Timestamp的使用总结
2021/12/06 MySQL
Python TypeError: ‘float‘ object is not subscriptable错误解决
2022/12/24 Python