【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 ...
随机推荐
- .NET CORE 多语言实现方案
根据市场需求,基于.NET CORE平台开发的RoadFlow工作流平台需要实现多语言版本.经过方案讨论和比对,决定采用.NET自带的本地化功能来实现多语言.话不多说,直接上实现方式. 首先修改Sta ...
- BAT的人都是怎么学习的
不知道你发现没,在技术领域走在前列的人,基本都符合一个条件:保持对新技术的敏感度,还能定期更新自己的技能储备. 要做到这一点,最高效的办法就是直接跟 BAT 等一线大厂取经.说白了,平台足够大,就有更 ...
- The Summer Training Summary-- the first
The Summer Training Summary-- the first A - vector的使用 UVa 101 关于vector 的几个注意点 vector p p.push_back() ...
- c++小游戏——三国杀
#include<iostream> #include<time.h> #include<stdio.h> #include <stdlib.h> us ...
- 【MySQL】(六)锁
开发多用户.数据库驱动的应用时,最大的一个难点是:一方面要最大程度地利用数据库的并发访问,另一方面还要确保每个用户能以一致的方式读取和修改数据.为此就有了锁(locking)的机制,同时这也是数据库系 ...
- Java用户程序
Java的用户程序分为两类:Java Application和Java Applet. 这两类程序在程序结构和执行机制上有一定的差异. Java Application是完整的程序,需要独立的Java ...
- 下载Opencv和OpencvSharp,让我们开始图像之旅
我们学习和使用OpencvSharp,还下载Opencv干什么?很简单,研究人家的源码是最好和最快速的学习方式. 第一Opencv源码下载,网络上很多,请大家自行搜索,版本请下载4.1.0.当前你要用 ...
- 入门训练-1.A+B问题
问题描述 输入A.B,输出A+B. 说明:在“问题描述”这部分,会给出试题的意思,以及所要求的目标. 输入格式 输入的第一行包括两个整数,由空格分隔,分别表示A.B. 说明:“输入格式”是描述在测试你 ...
- 2048 控制台版(C#)
开篇 2048游戏现在很火啊,很多人应该已经玩过了.在博客园上也看见有人模仿做的GDI+版 2048游戏,鄙人暂且不做那么多动画的东西,毕竟是个小东东,在此奉上一个<控制台版2048>. ...
- jQuery表单校验
主要特性: 表单提交前对所有数据进行校验,不符合不让提交(validate) 如果表单校验不通过,自动focus到第一个错误的域 自动在控件后面显示错误提示内容(error message) 支持根据 ...