JS引擎线程的执行过程的三个阶段(二)
继续JS引擎线程的执行过程的三个阶段(一) 内容, 如下:
三. 执行阶段
1. 网页的线程
永远只有JS引擎线程在执行JS脚本程序,其他三个线程只负责将满足触发条件的处理函数推进事件队列,等待JS引擎线程执行, 不参与代码解析与执行。
JS引擎线程: 也称为JS内核,负责解析执行Javascript脚本程序的主线程(例如V8引擎)
事件触发线程: 归属于浏览器内核进程,不受JS引擎线程控制。主要用于控制事件(例如鼠标,键盘等事件),当该事件被触发时候,事件触发线程就会把该事件的处理函数推进事件队列,等待JS引擎线程执行
定时器触发线程:主要控制计时器setInterval和延时器setTimeout,用于定时器的计时,计时完毕,满足定时器的触发条件,则将定时器的处理函数推进事件队列中,等待JS引擎线程执行。 注:W3C在HTML标准中规定setTimeout低于4ms的时间间隔算为4ms。
HTTP异步请求线程:通过XMLHttpRequest连接后,通过浏览器新开的一个线程,监控readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进事件队列中,等待JS引擎线程执行。 注:浏览器对通一域名请求的并发连接数是有限制的,Chrome和Firefox限制数为6个,ie8则为10个。
2. 宏任务
宏任务(macro-task)可分为同步任务和异步任务:
同步任务指的是在JS引擎主线程上按顺序执行的任务,只有前一个任务执行完毕后,才能执行后一个任务,形成一个执行栈(函数调用栈)。
异步任务指的是不直接进入JS引擎主线程,而是满足触发条件时,相关的线程将该异步任务推进任务队列(task queue),等待JS引擎主线程上的任务执行完毕,空闲时读取执行的任务,例如异步Ajax,DOM事件,setTimeout等。
理解宏任务中同步任务和异步任务的执行顺序,那么就相当于理解了JS异步执行机制–事件循环(Event Loop)。
3. 事件循环
事件循环可以理解成由三部分组成,分别是:
主线程执行栈
异步任务等待触发
任务队列
任务队列(task queue)就是以队列的数据结构对事件任务进行管理,特点是先进先出,后进后出。

setTimeout和setInterval的区别:
setTimeout是在到了指定时间的时候就把事件推到任务队列中,只有当在任务队列中的setTimeout事件被主线程执行后,才会继续再次在到了指定时间的时候把事件推到任务队列,那么setTimeout的事件执行肯定比指定的时间要久,具体相差多少跟代码执行时间有关
setInterval则是每次都精确的隔一段时间就向任务队列推入一个事件,无论上一个setInterval事件是否已经执行,所以有可能存在setInterval的事件任务累积,导致setInterval的代码重复连续执行多次,影响页面性能。
4. 微任务
微任务是在es6和node环境中出现的一个任务类型,如果不考虑es6和node环境的话,我们只需要理解宏任务事件循环的执行过程就已经足够了,但是到了es6和node环境,我们就需要理解微任务的执行顺序了。 微任务(micro-task)的API主要有:Promise, process.nextTick

例子理解:
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
执行过程如下:
代码块通过语法分析和预编译后,进入执行阶段,当JS引擎主线程执行到console.log('script start');,JS引擎主线程认为该任务是同步任务,所以立刻执行输出script start,然后继续向下执行;
JS引擎主线程执行到setTimeout(function() { console.log('setTimeout'); }, 0);,JS引擎主线程认为setTimeout是异步任务API,则向浏览器内核进程申请开启定时器线程进行计时和控制该setTimeout任务。由于W3C在HTML标准中规定setTimeout低于4ms的时间间隔算为4ms,那么当计时到4ms时,定时器线程就把该回调处理函数推进任务队列中等待主线程执行,然后JS引擎主线程继续向下执行
JS引擎主线程执行到Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); });,JS引擎主线程认为Promise是一个微任务,这把该任务划分为微任务,等待执行
JS引擎主线程执行到console.log('script end');,JS引擎主线程认为该任务是同步任务,所以立刻执行输出script end
主线程上的宏任务执行完毕,则开始检测是否存在可执行的微任务,检测到一个Promise微任务,那么立刻执行,输出promise1和promise2
微任务执行完毕,主线程开始读取任务队列中的事件任务setTimeout,推入主线程形成新宏任务,然后在主线程中执行,输出setTimeout
最后的输出结果即为:
script start
script end
promise1
promise2
setTimeout
文章参考:
https://github.com/yygmind/blog/issues/12
https://heyingye.github.io/2018/03/19/js引擎的执行过程(一)
https://heyingye.github.io/2018/03/26/js引擎的执行过程(二)
https://github.com/yygmind/blog
JS引擎线程的执行过程的三个阶段(二)的更多相关文章
- JS引擎线程的执行过程的三个阶段(一)
浏览器首先按顺序加载由<script>标签分割的js代码块,加载js代码块完毕后,立刻进入以下三个阶段,然后再按顺序查找下一个代码块,再继续执行以下三个阶段,无论是外部脚本文件(不异步加载 ...
- JS的解析与执行过程
JS的解析与执行过程 全局中的解析和执行过程 预处理:创建一个词法环境(LexicalEnvironment,在后面简写为LE),扫描JS中的用声明的方式声明的函数,用var定义的变量并将它们加到预处 ...
- 对象回收过程?线程池执行过程? map原理?集合类关系?synchronized 和 volatile ? 同一个类的方法事务传播控制还有作用吗?java 锁
1. 对象回收过程? 可达性分析算法: 如果一个对象从 GC Roots 不可达时,则证明此对象不可用. 通过一系列称为GC ROOTS的对象作为起点,从这些起点往下搜索,搜索走过的路径 称为引用链 ...
- JS的解析与执行过程—全局预处理阶段之全局词法环境对象
问题:有如下代码 var a = 1; function pop() { alert(a); var a = 5; } pop();//执行结果,弹出undefined 这段代码的执行结果为undef ...
- JS的解析与执行过程—函数预处理
声明:之所以分为全局预处理与函数预处理,只是为了理解方便,其实在实际运行中二者是不分先后的. 函数预处理阶段与全局预处理的差别: 函数每调用一次,就会产生一个LexicalEnviroment对象,在 ...
- JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略
有如下代码: <body> <script> alert(f); function f() { console.log("fff"); } var f = ...
- 【JS】js引擎执行过程
概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 语法分析: 分别对加载完成的代码块进行语法检验,语法正 ...
- (转载)js引擎的执行过程(二)
概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 语法分析: 分别对加载完成的代码块进行语法检验,语法正 ...
- (转载)js引擎的执行过程(一)
概述 js是一种非常灵活的语言,理解js引擎的执行过程对我们学习javascript非常重要,但是网上讲解js引擎的文章也大多是浅尝辄止或者只局部分析,例如只分析事件循环(Event Loop)或者变 ...
随机推荐
- pygame学习
http://eyehere.net/2011/python-pygame-novice-professional-3/ http://www.pygame.org/docs/ref/event.ht ...
- JavaScript 深拷贝(deep copy)和浅拷贝(shallow copy)
参考: [进阶4-1期]详细解析赋值.浅拷贝和深拷贝的区别 How to differentiate between deep and shallow copies in JavaScript 在编程 ...
- selenium python 设置窗口打开大小
1. 窗口最大化 1 driver.maximize_window() 2. 设置窗口大小 1 driver.set_window_size(1920,1080) #分辨率1920 x 1080
- python print 中文重定向失败
一直以来认为解决python字符集编码,不一定需要通过sys.setdefaultencoding.因为既然python实现过程中,默认禁用了该操作,说明是不推荐的. 通过不断的字符转换,也cover ...
- 问题:win7下配置好服务器就是不能查询数据库。(已解决)
我用C写访问mysql的CGI程序,可以执行. 但是,当我写好网页再去访问这个CGI,出现下面的错误 我的环境是:IIS作为服务器,MYSQL数据库,VC++6.0写CGI. 跟踪了一下,发现只要我调 ...
- python—迭代器、生成器
1.迭代器(iteration) 迭代器协议:提供next()方法,该方法要么返回迭代的下一项,要么异常.(只能往后走) 可迭代对象:实现迭代器协议的对象. **字符串.列表.元祖.字典.集合.文件都 ...
- php 将一个或多个二维数组组合成一个二维数组并根据某个字段排序排序
最近再写项目的时候,碰到一个问题:如何将一个或多个二维数组组合成一个二维数组并根据某个字段排序排序:实在是想不到哪个php库中有哪个函数能实现,只能自己写一个了,将代码写出来后,发现自己的代码繁琐,并 ...
- 百度地图API 自定义标注图标
通过Icon类可实现自定义标注的图标,下面示例通过参数MarkerOptions的icon属性进行设置, 也可以使用marker.setIcon()方法. <script type=" ...
- HTTP长连接和短连接 + Websocket
HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问题,T ...
- [Swift]LeetCode333. 最大的二分搜索子树 $ Largest BST Subtree
Given a binary tree, find the largest subtree which is a Binary Search Tree (BST), where largest mea ...