浅谈 Event loop (事件循环)
从Event Loop谈JS的运行机制
先来理解一个概念:
JS分为同步任务和异步任务
同步任务都在主线程上执行,形成一个
执行栈 Execute Content Stack主线程之外,事件触发线程管理着一个
任务队列,只要异步任务有了运行结果,就在任务队列(根据MDN准确的说应该是消息队列 message queue)之中放置一个消息(一般都是异步的回调函数)。一旦
执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取消息队列,将可运行的异步任务添加到可执行栈中,开始执行。
看图:

看到这里,应该就可以理解了:为什么有时候setTimeout推入的事件不能准时执行?因为可能在它推入到消息队列时,主线程还不空闲,正在执行其它代码,所以自然有误差。
事件循环机制进一步补充
这里就直接引用一张图片来协助理解:(参考自Philip Roberts的演讲《Help, I’m stuck in an event-loop》)

上图大致描述就是:
主线程运行时会产生执行栈,栈中的代码调用某些api时,它们会在事件队列中添加各种事件(当满足触发条件后,如ajax请求完毕)
而栈中的代码执行完毕,就会读取事件队列中的事件到执行栈中,去执行那些回调
如此循环
注意,总是要等待栈中的代码执行完毕后才会去读取消息队列中的消息
然后我们通过阅读Promise/A+规范,可以得知JS中分为两种任务类型,分别是macro-task和micro-task。
Macro-tasks包括: script(整体代码)、setTimeout, setInterval, setImmediate, I/O, UI Rendering;(可以看到,事件队列中的每一个事件都是一个macrotask)
Micro-tasks包括: process.nextTick, Promise, Object.observe(已废弃), MutationObserver。
总结下运行机制:
执行一个宏任务(栈中没有就从事件队列中获取)
执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
如图:
这里注意的是,UI Rendering是在micro-task之后执行,需要在UI渲染之前执行的逻辑,一般采用micro-task异步回调方式进行调用。 同样,micro-task队列不宜过长,给micro-task队列添加过多回调阻塞macro-task队列的任务执行是小事,重点是这有可能会阻塞UI Render,导致页面不能更新。浏览器也会基于性能方面的考虑,对micro-task中的任务个数进行限制。
参考文章:
浅谈 Event loop (事件循环)的更多相关文章
- javascript的event loop事件循环
javascript的event loop事件循环 这是今天一个朋友发给我的一个面试题, 感觉还挺有意思的, 写个博客以供分享 先看看这个面试题目: 观察下面的代码,写出输出结果 console.lo ...
- node.js中对Event Loop事件循环的理解
javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进 ...
- 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?
https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...
- Event Loop事件循环,GET!
JS中比较让人头疼的问题之一要算异步事件了,比如我们经常要等后台返回数据后进行dom操作,又比如我们要设置一个定时器完成特定的要求.在这些同步与异步事件里,异步事件肯定是在同步事件之后的,但是异步事件 ...
- 进程,线程,Event Loop(事件循环),Web Worker
线程,是程序执行流的最小单位.线程可与同属一个进程的其他线程共享所拥有的全部资源,同一进程中的多个线程之间可以并发执行.线程有就绪,阻塞,运行三种基本状态. 阮一峰大神针对进程和线程的类比,很是形象: ...
- js event loop事件循环
浏览器环境 以下两段代码是等价的.req对事件的回调设置,实际上就是当前主线程任务队列的任务. var req = new XMLHttpRequest(); req.open('GET', url) ...
- JavaScript event loop事件循环 macrotask与microtask
macrotask 姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...
- JavaScript 运行机制详解:再谈Event Loop
原文地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Eve ...
- javascript运行机制详解: 再谈Event Loop(转)
作者: 阮一峰 日期: 2014年10月 8日 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Event Loop的理解. 上个月,我偶然看到了Philip Roberts ...
随机推荐
- JavaScript Boolean( new Boolean(false) ) 其实是true
Boolean类型是JavaScript原始数据类型(primitive type)之一:常用来表示 真或假,是或否:这个类型只有两个值:保留字true和false 一般用于控制语句:如下 if(Bo ...
- AndroidStudio打包apk,安装出现签名冲突--解决办法
Android UiAutomator2项目部署到jenkins上,实现自动打包,并自动push&安装到设备上 遇到问题: 可成功实现自动打包并push到设备上后,install -r 的时候 ...
- javascript数据结构与算法---二叉树(查找最小值、最大值、给定值)
javascript数据结构与算法---二叉树(查找最小值.最大值.给定值) function Node(data,left,right) { this.data = data; this.left ...
- 用SpringSecurity从零搭建pc项目-02
参照这一篇文章吧,比如你不需要做的那么通用,取其中一部分代码即可. https://www.cnblogs.com/lihaoyang/p/8491792.html
- ASP.NET Core 中使用 GrayLog 记录日志
使用 UDP 协议发送日志 自定义好的查询 key 存储数据,尽量不要使用 graylog2-server 服务端格式化日志再存储 Ubuntu 安装服务端 sudo apt-get update & ...
- System.Threading.Tasks.Task 引起的 IIS 应用池崩溃
接口服务运行一段时间后,IIS应用池就会突然挂掉,事件查看日志,会有事件日志Event ID为5011的错误 为应用程序池“PokeIn”提供服务的进程在与 Windows Process Activ ...
- 记一次cocos项目的加载速度优化
半个月前,我们用cosos creator做了一个简单的小游戏,也许算不上小游戏吧..一边学cocos,一边做,几经波折后终于上线了.然鹅,功能是实现了,但是加载速度十分感人(毕竟没经验嘛,无辜脸). ...
- [转]Android中handler机制的原理
Andriod提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange). 1)Loo ...
- 一口一口吃掉Hexo(四)
如果你想得到更好的阅读效果,请访问我的个人网站 ,版权所有,未经许可不得转载! 人总是不会满足于现状,接下来我们就可以让我们的朋友们通过独立域名访问我们的网站了,但是这肯定是要花点钱的,所以这篇文章难 ...
- Android 开发工具类 33_开机自运行
原理:该类派生自 BroadcastReceiver,重载方法 onReceive ,检测接收到的 Intent 是否符合 BOOT_COMPLETED,如果符合,则启动用户Activity. imp ...