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
在 事件循环 期间的某个时刻,运行时会从最先进入队列的消息开始处理队列中的消息.被处理的消息会被移出队列,并作为输入参数来调用与之关联的函数.正如前面所提到的,调用一个函数总是会为其创造一个新的栈帧. ...
随机推荐
- Digits of Factorial LightOJ - 1045
题目就不再发了,大致意思就是给你一个十进制数n,算出阶乘后转换成K进制的数,你来算一下它的位数. 坑点在哪呢,就是这个数可能算阶乘的时候没放弄了,比如1000000,做过最多单算阶乘的题也就是让你算到 ...
- uni-app去掉h5端的导航栏
找到项目的根目录下的pages.json文件,添加一下内容,可以去掉对应页面的导航栏 附上代码 "app-plus":{ "titleNView": false ...
- 整数m去掉n位后剩下最大(小)值
题目描述 给定一个正整数(<=255位),从中删去n位后,使得剩下的数字组成的新数最小(大): 思路:从左到右开始扫描,两两比较,如果是前一位比后一位大,则删去前大的一位,直到删完所有的n位: ...
- 力扣(LeetCode) 66. 加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一. 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字. 你可以假设除了整数 0 之外,这个整数不会以零开头. 示例 1: 输入 ...
- python模块(3)
1.xml:实现不同语言或程序之间进行数据交换的协议 <data> <country name="Liechtenstein"> <rank upda ...
- d3选择全部子节点,不知道class和id
https://github.com/d3/d3-selection/issues/63 selection.selectAll("*")
- 牛客网NOIP赛前集训营-提高组(第一场)A 中位数
中位数 思路: 二分答案 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ...
- English trip EM2-LP-6B Teacher:Gabriele
Gabriele Gabi n. 加布里尔,加布里埃尔,加布里埃,加布里埃莱(人名) 课上内容(Lesson) 词汇(Key Word ) is married? 结 ...
- (GoRails)在导航栏增加自动的搜索功能(jquery插件:easyautocomplete)(gem 'ransack' 搜索对象4000✨)
Global Autocomplete Search 需要用到一个JQuery插件和一个搜索对象的gem EasyAutocomplete jQuery插件: https://github.com/p ...
- spring boot(一)入门
什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员 ...