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
在 事件循环 期间的某个时刻,运行时会从最先进入队列的消息开始处理队列中的消息.被处理的消息会被移出队列,并作为输入参数来调用与之关联的函数.正如前面所提到的,调用一个函数总是会为其创造一个新的栈帧. ...
随机推荐
- 清除div重叠浮动的方法
在最后加入这样一个div. 并且为div加入以下属性: .clear { clear:both;}
- JDBC的通用查询的方法
PreparedStatement 1.Why 1):使用Statement需要进行拼写SQL语句,很辛苦,而且容易出错. 2):使用Statement可以发生SQL注入. SQl注入: SQL注入是 ...
- docker-compose在dockerfile更新后自动更新image
比如在dockerfile里需要新安装包 形如 加一行 RUN pip3 install XXX 之后,希望docker-compose能更新镜像, 然后启动容器 只需要启动时使用 --build即可 ...
- AD中的library中有些文件的后缀有.intlib .schlib .pcblib 这些都是库文件,但有什么区别呢?
intlib 是集成原理图和PCB封装的 schlib .只有原理图 pcblib 只有PCB封装 参考资料 1 https://zhidao.baidu.com/question/259298801 ...
- 牛客小白月赛7 CSL的校园卡
CSL的校园卡 思路: bfs,用状压表示走过的区域,然后和x1,y1,x2,y2构成所有的状态,然后标记一下就可以了 代码: #pragma GCC optimize(2) #pragma GCC ...
- java 数据导入xls
@RequestMapping("admin/doorDesign/getexcel.do") public void getExcel(String name,String ph ...
- mac显示影藏文件
http://blog.csdn.net/xiaoyuanzhiying/article/details/46694577 然后finder强制退出,然后重启.
- 理解css相邻兄弟选择器
今天在菜鸟教程看到了css组合选择符的“相邻兄弟选择器”,刚开始对这个概念有些不太理解,通过查阅资料并且经过一些试验总算有了些头绪. 原文解释是“相邻兄弟选择器(Adjacent sibling se ...
- maven 把本地jar包打进本地仓库
maven 把本地jar包打进本地仓库 1.本地有自己写的项目jar包,但是需要用maven依赖对其进行引用: 2.某个jar包在远程仓库没有,导致pom.xml报错,此时可以从网上单独下载此jar包 ...
- python3 语法小结
(1) 关键字 # -*- coding: utf-8 -*- #!/usr/bin/python3 """ 1.关键字(保留字) ['False', 'None', ' ...