JavaScipt 中的事件循环(event loop),以及微任务 和宏任务的概念
说事件循环(event loop)之前先要搞清楚几个问题。
- JavaScript引擎线程,用于解析JavaScript代码
- GUI渲染线程,(它与javaScript线程是互斥的)
- 事件线程(onclick,onchange,…)
- 定时器线程(setTimeout, setInterval)
- 异步http线程(ajax),负责数据请求
- EventLoop轮询处理线程,事件被触发时该线程会把事件添加到待处理队列的队尾
- javaScript 中的任务可以被划分为宏任务(Macrotask)或者微任务(Microtask)。
- 像鼠标事件,键盘事件,"ajax","setTimeout"等就属于宏任务,需要注意的是,主线程的整体代码(script标签),也是一个宏任务
- process.nextTick,PromiseA.then(), MutaionObserver 就属于微任务

网上有用异步任务和同步任务来说明这个问题的,但是我觉得用宏任务和微任务更好点。
console.log(1);
setTimeout(function(){
console.log(2)
},10);
new Promise(function(resolve){
console.log(3)
for( var i=100000 ; i>0 ; i-- ){
i==1 && resolve()
}
console.log(4)
}).then(function(){
console.log(5)
}).then(function(){
console.log(6)
})
console.log(7);
打印出来的结果是:1 3 4 7 5 6 2
我们分析一下整个过程
1. 首先执行主线程这个宏任务,从上到下执行,遇到console.log(1); 打印1出来
2. 遇到setTimeout,把它丢给定时器线程处理,然后继续往下执行,并不会阻塞10毫秒,而此处定时器线程会在,主线程执行完后的10毫秒,把回调函数放入宏任务队列。
3. 遇到new Promise,直接执行,先打印 ‘3‘ 出来,然后执行for循环,达到条件之后,把promise的状态改为resolved,继续执行打印 ‘4’ 出来
4.遇到promise的then, 属于微任务,则把回调函数放入微任务队列
5.又遇到promise的then, 属于微任务,则把回调函数放入微任务队列
6. 遇到console.log(7) 打印 ‘7’ 出来
7. 宏任务执行完后会执行所有待执行的微任务,所以会相继打印 ‘6’, ‘7’ 出来。
至此第一轮循环已经结束了,第一轮循环里的宏任务和微任务都会被移除出任务队列,接下来开启第二轮循环,
1.首先查找是否有宏任务,由于setTimeout 的回调被放入了宏任务队列,这里会执行回调函数的代码,打印了 ‘2’ 出来
2. 接着查找是否有微任务,发现没有微任务,则本轮循环结束
接下来会重复上面的步骤,这就是event loop 了。后续当我们触发点击事件,有回调函数的话,回调函数也会被放入宏任务队列,一旦队列里重新有了任务,就会被执行。
6. 扩展题目
如果能把上面这道题的流程说清楚,那么恭喜你,对event loop理解的不错了。 下面我们再利用上面的题目扩展一下,加深理解。
下面的代码打印出来的结果是什么?
console.log(1);
setTimeout(function(){
new Promise(function(resolve){
console.log('promise in setTimeout1');
resolve();
}).then(function(){
console.log('then in setTimeout1');
})
},10);
new Promise(function(resolve){
console.log(3);
for( var i=100000 ; i>0 ; i-- ){
i==1 && resolve();
}
console.log(4)
}).then(function(){
console.log(5);
});
setTimeout(function(){
console.log('setTimeout2');
},10);
console.log(7);
结果如下:

可以发现,第二个setTimeout 的回调函数,执行的比第一个setTimeout里面的promise.then()的回调要晚,这是因为每次循环只执行一个宏任务,但是却会执行所有待执行的微任务,而第二个setTimeout在宏任务队列的位置在第一个setTimeout后面。
这个就是我理解的JavaScipt 事件循环机制,参考了很多文章,也自己做了很多思考写出来的,码字不易,觉得有帮助可以点个赞哦。也欢迎留言交流
参考文章
https://segmentfault.com/a/1190000012806637?utm_source=tag-newest
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
https://zhuanlan.zhihu.com/p/33127885
https://zhuanlan.zhihu.com/p/33136054
https://stackoverflow.com/questions/25915634/difference-between-microtask-and-macrotask-within-an-event-loop-context
JavaScipt 中的事件循环(event loop),以及微任务 和宏任务的概念的更多相关文章
- 简单了解一下事件循环(Event Loop)
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- JS事件循环(Event Loop)机制
前言 众所周知,为了与浏览器进行交互,Javascript是一门非阻塞单线程脚本语言. 为何单线程? 因为如果在DOM操作中,有两个线程一个添加节点,一个删除节点,浏览器并不知道以哪个为准,所以只能选 ...
- 事件循环 event loop 究竟是什么
事件循环 event loop 究竟是什么 一些概念 浏览器运行时是多进程,从任务管理器或者活动监视器上可以验证. 打开新标签页和增加一个插件都会增加一个进程,如下图:  浏览器渲染进程是多线程,包 ...
- 事件循环Event loop到底是什么
摘要:本文通过结合官方文档MDN和其他博客深入解析浏览器的事件循环机制,而NodeJS有另一套事件循环机制,不在本文讨论范围中.process.nextTick和setImmediate是NodeJS ...
- 浏览器与Node的事件循环(Event Loop)有何区别?
前言 本文我们将会介绍 JS 实现异步的原理,并且了解了在浏览器和 Node 中 Event Loop 其实是不相同的. 一.线程与进程 1. 概念 我们经常说 JS 是单线程执行的,指的是一个进程里 ...
- JavaScript事件循环(Event Loop)机制
JavaScript 是单线程单并发语言 什么是单线程 主程序只有一个线程,即同一时间片断内其只能执行单个任务. 为什么选择单线程? JavaScript的主要用途是与用户互动,以及操作DOM.这决定 ...
- JavaScript 事件循环 — event loop
引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...
- 一文梳理JavaScript 事件循环(Event Loop)
事件循环(Event Loop),是每个JS开发者都会接触到的概念,但是刚接触时可能会存在各种疑惑. 众所周知,JS是单线程的,即同一时间只能运行一个任务.一般情况下这不会引发问题,但是如果我们有一个 ...
- 事件循环Event Loop
在 事件循环 期间的某个时刻,运行时会从最先进入队列的消息开始处理队列中的消息.被处理的消息会被移出队列,并作为输入参数来调用与之关联的函数.正如前面所提到的,调用一个函数总是会为其创造一个新的栈帧. ...
随机推荐
- JavaEE编程实验 实验1 Java常用工具类编程(未完成)
1.使用String类分割split将字符串“Solutions to selected exercises can be found in the electronic document The T ...
- Java学习必备书籍推荐终极版!
Java 基础 <Head First Java>(推荐,豆瓣评分 8.7,1.0K+人评价): 可以说是我的 Java 启蒙书籍了,特别适合新手读当然也适合我们用来温故 Java 知识点 ...
- kafka+docker+python
昨天晚上刚刚才花3小时看完<日志:每个软件工程师都应该知道的有关实时数据的统一概念>. 今天就把kafka在docker容器里运行起来,github上有几个,但都太复杂了. 我自己写个最简 ...
- Codeforces 1077 F2 - Pictures with Kittens (hard version)
F2 - Pictures with Kittens (hard version) 思路: 单调队列优化dp 代码: #pragma GCC optimize(2) #pragma GCC optim ...
- 牛客国庆集训派对Day3 B Tree
Tree 思路: 树形dp 注意0不存在逆元,任何一个数乘以0就变成0了,就没有价值浪,所以要暴力转移 代码: #pragma GCC optimize(2) #pragma GCC optimize ...
- Codeforces 985 F - Isomorphic Strings
F - Isomorphic Strings 思路:字符串hash 对于每一个字母单独hash 对于一段区间,求出每个字母的hash值,然后排序,如果能匹配上,就说明在这段区间存在字母间的一一映射 代 ...
- zabbix自定义监控方式
- 日常英语---二、注册google的api的key
日常英语---二.注册google的api的key 一.总结 一句话总结:register google api key register_google_api_key 1.请通过电子邮件向我发送有关 ...
- (转)C# System.Diagnostics.Process.Start使用
经常会遇到在Winform或是WPF中点击链接或按钮打开某个指定的网址, 或者是需要打开电脑中某个指定的硬盘分区及文件夹, 甚至是"控制面板"相关的东西, 如何做呢? 方法:使用 ...
- 雷林鹏分享: XML CDATA
XML CDATA XML 文档中的所有文本均会被解析器解析. 只有 CDATA 区段中的文本会被解析器忽略. PCDATA - 被解析的字符数据 XML 解析器通常会解析 XML 文档中所有的文本. ...