美文网首页互联网科技
JS引擎线程的执行过程的三个阶段(二)

JS引擎线程的执行过程的三个阶段(二)

作者: 吉古力 | 来源:发表于2019-02-25 21:31 被阅读1次

继上一篇文章 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引擎线程的执行过程的三个阶段(一) 三. 执行阶段 1. 网页的线程 永远只有JS引擎线程在执行...

  • JS引擎线程的执行过程的三个阶段(一)

    浏览器首先按顺序加载由 标签分割的js代码块,加载js代码块完毕后,立刻进入以下三个阶段,然后再按顺序查找下一个代...

  • 怎么来理解Js是单线程的这句话?

    Js是单线程指的是执行Js代码的只有Js引擎主线程。Js在js引擎中同步执行,永远都是运行执行栈最顶部的代码。那么...

  • 5.js引擎执行代码的过程

    先来看看js引擎执行代码的过程:代码执行分为两个过程,先是分析阶段(可以理解为执行准备阶段),然后是真正执行阶段。...

  • javascript 执行上下文

    javascript 是单线程语言 javascript 是异步执行的,通过事件循环的方式进行 js引擎执行过程分...

  • JS的加载

    JS采用单线程,避免在执行过程中页面内内容被不可预知的重复修改 js的五个常驻线程 浏览器的GUI渲染线程JS引擎...

  • 深入了解JavaScript执行过程(JS系列之一)

    前言 JavaScript 执行过程分为两个阶段,编译阶段和执行阶段。在编译阶段 JS 引擎主要做了三件事:词法...

  • 白话JS引擎运行过程

    JS引擎对代码解析执行的过程,有两个阶段。第一个阶段是构建语法树。第二个阶段是对语法树进行解析执行。 第一阶段:构...

  • JavaScript 执行机制

    五个线程 js引擎线程: 执行js代码GUI线程: 绘制用户界面http网络请求线程: 处理网络请求, 等请求返回...

  • javascript的同步异步编程

    js中的同步和异步 同步js是单线程的,浏览器只会分配一个js引擎线程,用来执行js代码,当其执行代码时,js一次...

网友评论

    本文标题:JS引擎线程的执行过程的三个阶段(二)

    本文链接:https://www.haomeiwen.com/subject/jwynyqtx.html