【JS档案揭秘】第二集 Event loop与执行栈
我时常在思考关于JS的很多知识在工作中有什么用?是否只能存在于面试这种理论性的东西中,对于我们的业务和工作,它们又能扮演怎样的角色。以后在JS档案揭秘的每一期里,都会加入我对于业务的思考,让这些知识不再是空中楼阁,而是有实际操作的意义。
业务场景
所有的核心在于执行顺序,它能帮助我们正确判断代码按照怎样的顺序去执行。避免因为执行顺序与预期不一致而导致的bug。如果遇到这种因为执行顺序问题而产生的bug,也能通过event loop分析出正确的执行顺序,定位bug并解决。
关键词解释
执行栈:一个专门用来存放执行代码的栈内存结构,它就像一个容器,也叫做执行的主线程。如果遇到函数,会根据回调关系把回调层级深的函数先推入到执行栈底部执行,其他语句依次推入,当全部执行完了后,会从上到下依次弹出执行代码(也就是“先进后出”),供下一次使用;
宏任务(只针对浏览器环境):宿主环境提供的任务,包括:script代码块,MessageChannel,requestAnimationFrame,setTimeout,setInterval;
微任务(只针对浏览器环境):JS自带的任务,包括promise的then和catch,MutationObserver;
任务队列:由宏任务队列与微任务队列组成;
event loop:又名事件循环,它会不断地去微任务队列里取任务放到执行栈执行,当微任务队列被清空时,才去宏任务队列取任务执行。假如这个宏任务里面碰到了微任务和宏任务,会分别推入到任务队列中,并按照“只有微任务队列清空才执行宏任务”的原则来执行代码;
画图理解

过程叙述
当我们说“浏览器是 JS 的家”时,这句话真正的意思是浏览器提供运行时环境来执行我们的JS代码。
浏览器的主要组件包括JS引擎,事件循环,任务队列和Web APIs。上图的任务队列有一点瑕疵,任务队列应该有两个(宏任务队列与微任务队列)。
JS引擎从堆中取出JS代码并及进行分析。假设是一段或多段script代码,它会被认为是一个或几个宏任务,并推入到web apis中。web apis看到是script代码,就把它推入到宏任务队列中,event loop从宏任务队列取到这一段JS代码,并放入执行栈中执行。
在执行当前宏任务时,每当它遇到一些异步代码,如setTimeout,它又会把它推入到web apis中去执行。当异步代码在Web APIs被执行完后,其回调callback 就被送往任务队列。
event loop不断地监视任务队列(Task Queue),并按它们排队的顺序一次处理一个回调。每当调用栈为空,也就是同步代码执行完毕时,event loop会不断地去微任务队列里取任务放到执行栈执行,当微任务队列被清空时,才去宏任务队列取任务执行。请记住,如果调用栈不是空的,则事件循环不会将任何回调推入执行栈。
例题分析

按照我们之前的理论,首先这里分成两个宏任务,script1和script2。
script1的同步代码先执行,打印111,333。微任务队列推入222,宏任务队列推入444。
此时微任务队列只有222,而宏任务队列为“script2 --- 444”。
所以先清空微任务队列,打印出222,再从宏任务队列中取出script2,推到执行栈中执行。
script2的同步代码先执行,打印555,777。并将666推入微任务队列,888推入宏任务队列。
此时微任务队列只有666,而宏任务队列为“444 --- 888”。
所以先清空微任务队列,打印出666,再从宏任务队列依次取出444和888,并推到执行栈中执行。
综上,打印结果如下:

【JS档案揭秘】第二集 Event loop与执行栈的更多相关文章
- Node.js的事件轮询Event Loop原理
Node.js的事件轮询Event Loop原理解释 事件轮询主要是针对事件队列进行轮询,事件生产者将事件排队放入队列中,队列另外一端有一个线程称为事件消费者会不断查询队列中是否有事件,如果有事件,就 ...
- js事件循环机制 (Event Loop)
一.JavaScript是单线程单并发语言 什么是单线程 主程序只有一个线程,即同一时间片断内其只能执行单个任务. 为什么选择单线程? JavaScript的主要用途是与用户互动,以及操作DOM.这决 ...
- js的事件循环(Event Loop)
(本文从掘金小册整理) 首先介绍一下几个概念 进程与线程 相信大家经常会听到 JS 是单线程执行的,但是你是否疑惑过什么是线程? 讲到线程,那么肯定也得说一下进程.本质上来说,两个名词都是 CPU 工 ...
- 对Node.JS的事件轮询(Event Loop)的理解
title: Node.JS的事件轮询(event loop)的理解 categories: 理解 tags: Node JS 机制 当我们知道I/O操作和创建新线程的开销是巨大的! 网站延迟的开销 ...
- 【JS档案揭秘】第一集 内存泄漏与垃圾回收
程序的运行需要内存,对于一些需要持续运行很久的程序,尤其是服务器进程,如果不及时释放掉不再需要的内存,就会导致内存堆中的占用持续走高,最终可能导致程序崩溃. 不再需要使用的内存,却一直占用着空间,得不 ...
- 【JS档案揭秘】第四集 关于this的讨论到此为止
网上关于this的指向问题的博客文章很多,但大多数都是复制粘贴,也不能用简洁的语言讲清楚,而是不停地写一些示例,看得人云里雾里. 这一集,我只给出结论,以及判定的通用方法,至于是否确实如我所讲,大家可 ...
- 【JS档案揭秘】第三集 深入最底层探秘原型链
关于这部分我看过大量的文章,数不胜数,包括阮一峰的继承三部曲,还有各种慕课的视频教程,网上无数继承方法的对比.也对很多概念存在长期错误的理解.今天做一个正确的总结,用来给原型链和继承这块知识画上句号, ...
- js 在浏览器中的event loop事件队列
目录 前言 认识一个栈两个队列 执行过程 异步任务怎么分配 简单例子 难一点的例子 前言 以下内容是js在浏览器中的事件队列执行,与在nodejs中有所区别,请注意. 都说js是单线程的,不过它本身其 ...
- Js 运行机制和Event Loop
一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...
随机推荐
- Zeppelin 0.6.2使用Spark的yarn-client模式
Zeppelin版本0.6.2 1. Export SPARK_HOME In conf/zeppelin-env.sh, export SPARK_HOME environment variable ...
- c++小游戏——扫雷
#include<cstdio> #include<cstring> #include<algorithm> #include<conio.h> #in ...
- 钉钉E应用(小程序)之日历
唠叨几句:其实钉钉E应用的编写类似支付宝小程序(毕竟是阿里爸爸下的产业),而支付宝小程序又是chao xi 微信小程序(只不过人家是wxml / wxss ,他是 axml / acss罢了),这三者 ...
- 使用 Spring Framework 时常犯的十大错误
Spring 可以说是最流行的 Java 框架之一,也是一只需要驯服的强大野兽.虽然它的基本概念相当容易掌握,但成为一名强大的 Spring 开发者仍需要很多时间和努力. 在本文中,我们将介绍 Spr ...
- nginx(二)
nginx rewrite Nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向.rewrite只能放在server{},location{},if{}中,并且 ...
- Java 虚拟机部分面试题
Java虚拟机部分的面试内容包括三部分:GC.类加载机制以及内存 Java内存区域 JVM内存分为哪几部分,这些部分分别都存储哪些数据? 线程隔离的数据区:程序计数器.Java虚拟机栈.本地方法栈. ...
- linux下的FTP安装及调优
前言: 在之前交换平台的开发中,FTP的各种操作算是核心功能点. 在FTP的开发中,遇到了不少坑. 如FTP需要设置被动模式,否则10M以上的包可能会上传失败. 如FTP需要设置囚牢模式,否则访问的文 ...
- opencv编译
1. clone源码 https://github.com/opencv/opencv 2. 安装cmake 3. cmake配置的时候,输出目录需要另外设置一个目录,不可以放到源码目录 4. 用cm ...
- windows上node开发注意事项
windows上进行node.react开发的必要步骤: 1.使用nvm进行node及npm包管理工具,记得使用npm config set ...:2.另外react仅支持python3.0以下的版 ...
- Pivotal:15分钟部署你的应用
“ 本篇文章介绍的是PaaS平台Pivotal Cloud Foundry(以下简称PCF)的初步使用,相比于传统的IaaS平台(比如阿里云),PCF可实现快速迭代开发与部署,让您专注于业务开发.” ...