JavaScript Event Loop和微任务、宏任务
为什么JavaScript是单线程?
JavaScript的一大特点就是单线程, 同一时间只能做一件事情,主要和它的用途有关, JavaScript主要是控制和用户的交互以及操作DOM。注定它是单线程。 假如是多个线程, 一个移除DOM节点,一个新增DOM节点,浏览器以谁的为准呢?
什么是执执行栈呢?
函数的调用就会形成一个栈帧。当执行栈都为空的时候,主线程就会处于空闲状态。
function fn2(x, y) {
return x + y
}
function fn1(z) {
let a = 10
return fn2(a, z)
}
console.log(fn1(5)) // 15
以上代码: fn1 函数调用时会创建一个执行栈,栈中包含fn1的参数和局部变量。当 fn1 调用 fn2 时, 第二个执行栈就会被创建, 并且压入到第一个执行栈之前。 栈中包含了 fn2的参数和全局变量。当 fn2执行完返回时,最前面的执行栈就会被弹出。剩下 fn1 函数的调用帧, 当fn1 函数执行完并返回时, 执行栈就空了。
任务队列
任务队列主要用户挂起等待中的任务(异步任务)。
JavaScript是单线程, 意味着所有的任务需要排队, 前一个任务执行完,才能进行下一个任务。 AJAX就是典型的异步任务,需要调用HTTP线程,然后发送request请求,再是等待服务端的响应。在结果没有返回执行,后面的代码是不会执行的,这会给用户一种网站卡的现象。
因此, JavaScript 分为 同步任务在主线程上排队执行的任务,也就是前面执行完毕,才能执行下一个的任务。 异步任务是指它不会进行主线程,不会影响后续代码的执行,而是进入任务队列,当异步任务执行有了结果,就会在任务队列中放置一个事件,等主线程空闲(执行栈为空,同步任务执行完毕),通知任务队列进入主线程执行。
微任务和宏任务
任务队列中的异步任务分为 微任务和 宏任务
常见的微任务有: process.nextTick、Promise和 MutationObserver监听DOM的变化。
常见的宏任务: setTimeout、setInterval、setImmediate、 script中整体的代码、 I/O操作、 UI渲染等。
微任务和宏任务的区别:
- 微任务进入主线程执行是一队一队的, 而宏任务进入主线程是一个一个的。
- 微任务是在主线程空闲时批量执行, 宏任务是在事件循环下一轮的最开始执行
例子: 以下代码的打印结果
console.log(1)
setTimeout(function() {
console.log(2)
})
Promise.resolve()
.then(function() {
console.log(3)
})
console.log(4)
// 打印结果: 1 4 3 2
整个的执行过程:
stack(执行栈)、Micro(微任务)、Macro(宏任务)
1.初始状态: stack:[], Micro: [], Macro: [script]。执行栈为空, 微任务为空, 宏任务队列中有一个整体的 script代码
2. 主线程开始执行, 遇到console.log(1), 首先会打印 1
3. 继续向下执行,遇到 setTimeout异步任务,就将其加入到Macro(宏任务)队列中。等待执行
4. 继续向下执行, 遇到 Promise.resolve也是一个异步任务,单它是微任务,将其加入 Micro(微任务)队列中,等待着行
5. 解析console.log(4), 并且打印4。 当主线程执行完打印的结果依次是 1 和 4。
6. 这时候主线程就会问 任务(异步)队列,有没有微任务要执行,将所有的 Micro(微任务)加入执行栈执行, 打印结果 3
7. 微任务执行完了, 就开始下一轮事件循环, 将第一个 Macro(宏任务)压入执行栈执行, 再次打印 2。
Event Loop事件循环

只要主线程一空闲就会将 "任务队列中的异步任务"依次压入执行栈, 这个过程是循环不断的,所以整个运行机制称之为 Event Loop(事件循环)。
执行栈中(stack)的代码(同步任务),总是在读取"任务队列"(异步任务)之前执行。
图示

参考文章
JavaScript Event Loop和微任务、宏任务的更多相关文章
- Event Loop我知道,宏任务微任务是什么鬼?
在介绍宏任务和微任务之前,先抛出一个问题.相信大家在面试的时候,会遇到这样的相似的问题: setTimeout(function(){undefined console.log('1') }); ne ...
- javascript event loop
原文: https://blog.csdn.net/sjn0503/article/details/76087631 简单来讲,整体的js代码这个macrotask先执行,同步代码执行完后有micro ...
- JavaScript event loop事件循环 macrotask与microtask
macrotask 姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...
- javaScript Event Loop + NodeJs问题解析
http://www.ruanyifeng.com/blog/2014/10/event-loop.html https://github.com/ElemeFE/node-interview/tre ...
- 深入理解 JavaScript 事件循环(一)— event loop
引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...
- JavaScript事件循环(Event Loop)机制
JavaScript 是单线程单并发语言 什么是单线程 主程序只有一个线程,即同一时间片断内其只能执行单个任务. 为什么选择单线程? JavaScript的主要用途是与用户互动,以及操作DOM.这决定 ...
- JavaScript 事件循环 — event loop
引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...
- 【js基础修炼之路】- 微任务,宏任务和Event-Loop
一段代码让你了解Event-Loop console.log(1); setTimeout(() => { console.log(2); }, 0); new Promise((resolve ...
- event loop 与 vue
结论 对于event loop 可以抽象成一段简单的代码表示 for (macroTask of macroTaskQueue) { // 1. Handle current MACRO-TASK h ...
随机推荐
- 软件项目技术点(1)——d3.interpolateZoom-在两个点之间平滑地缩放平移
AxeSlide软件项目梳理 canvas绘图系列知识点整理 软件参考d3的知识点 我们在软件中主要用到d3.js的核心函数d3.interpolateZoom - 在两个点之间平滑地缩放平移.请 ...
- Canvas中的save方法和restore方法
初学者也许会误认为canvas中save方法是用来保存绘图状态的图形,而restore方法是用来还原之前保存的绘图状态的图形,其实不然. save():保存当前的绘图状态. restore():恢复之 ...
- 把连接中传的参数截取出来变成一个json对象
获取url function test() { var url=window.location.search; if(url.indexOf("?")!=-1) { var str ...
- C/C++ OpenCV读取视频与调用摄像头
原文:http://blog.csdn.net/qq78442761/article/details/54173104 OpenCV通过VideoCapture类,来对视频进行读取,调用摄像头 读取视 ...
- 命令行模式(CMD)下mysql查询中文显示乱码问题
mysql的默认编码已经设置为utf-8,用其他工具(代码,mysql workbench)写入或读出时显示正常,但用cmd查询时显示为乱码. 2.原因:mysql的客户端根本无法以utf-8的形式返 ...
- 微软与Node.js的开源之旅
微软近年来在开源领域可谓是大刀阔斧的前进中,继2015年微软与红帽合作,微软智能云Azure与Linux进一步融合等举措之后,2016年,微软继续加大开源之举,大力推进Node.js的开发和开源社区的 ...
- dctcp-2.6.26-rev1.1.0.patch
dctcp-2.6.26-rev1.1.0.patch diff -Naur linux-/include/linux/sysctl.h linux--dctcp-rev1.1.0/include/l ...
- Log4j的配置文件
附:Log4j比较全面的配置 Log4j配置文件实现了输出到控制台.文件.回滚文件.发送日志邮件.输出到数据库日志表.自定义标签等全套功能. log4j.rootLogger=DEBUG,consol ...
- 四、CentOS 安装mariadb——Linux学习笔记
A)安装及配置 下载mariadb: yum -y install mariadb-server mariadb 开启mariadb服务: systemctl start mariadb.servic ...
- 体验SpringBoot
体验SpringBoot 1.介绍 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开 ...