美文网首页
js线程执行原理

js线程执行原理

作者: 木中木 | 来源:发表于2019-09-30 08:38 被阅读0次

        众所周知,浏览器执行JS是单线程的,当然除了最新的worker线程,worker线程号称是浏览器端执行复杂运算一种解决方案,可以与主线程并行运算,而不互相排斥。浏览器线程主要分为以下三种:

1.就是我们熟悉的js线程,也就是js主引擎线程,执行js主线程代码。由于浏览器是单线程,所以浏览器无论什么时候都是一个线程在运行,这个线程也一直等待执行任务

2.GUI线程,执行dom树和css树回流和重绘。这里引起回流和重绘原因有很多种,都是由这个线程去处理,这里要注意的是GUI和js主引擎线程是互斥的,所以通常情况下,js引擎线程执行时间不能过长,过长就会引起GUI线程等待时间过长,页面就会造成卡顿。

3.事件触发线程,用于触发注册以及事件回调和异步代码执行。我们编写的异步代码(事件触发程序和settimeout),js主引擎执行到这些代码时,会先扔给事件触发线程,事件触发线程里面建立一个队列,按照先进先出的原则,依次把异步代码扔进队列,等待主线程空闲之后,再从触发线程队列中依次取出。

4.事件循环线程,用于管理我们的异步代码,存放到一个线程池中

    那我们熟悉这四个线程之后,我们就可以稍微明白js异步代码的执行原理,首先js异步代码并不是真正的异步代码,伪异步执行,只有在JS线程空闲的时候,才会去取监听线程代码程序。下面,我们阐述一下setTimeout执行原理。

比如:

`

console.log('+++++++++')

setTimeout(()=>{

    console.log('执行了异步代码');

},0);

console.log('==============')

`

主线程程序,按照顺序执行,遇到setTimeout,则是交给事件触发线程,由于时间是0,所以立即进去队列,然后主线程再去执行下面的代码,所以依次打印 ++++++++, =======,等到主线程空闲了,然后从事件循环线程中取出异步代码执行程序,执行settimeout,之后再打印'执行了异步代码'。

下面我们来看下一段代码

`

function threadDemo() {

    console.log(1);

    setTimeout(() => {

        console.log(2);

        Promise.resolve().then(() => {

            console.log(3)

        });

    }, 0);

    new Promise((resolve, reject) => {

        console.log(4)

        resolve(5)

    }).then((data) => {

        console.log(data);

    })

    Promise.resolve().then(() => {

        console.log('8');

    });

    setTimeout(() => {

        console.log(6);

    }, 0)

    console.log(7);

}

threadDemo();

`

如果你能知道最后的运行结果,就知道后面我们要讲述的内容。

js异步任务分为macrotask和mincrotask,这两个任务都是在主线程的某个时机放入任务队列中。

宏任务Macrotask, 在浏览器端,其可以理解为该任务执行完后,在下一个macrotask执行开始前,浏览器可以进行页面渲染:

    setTimeout / setInterval / setImmediate / IO / render / postMessage / script整体代码都是属于宏任务。

微任务mincrotask,可以理解为在macrotask任务执行后,页面渲染前立即执行的任务:

    promise.then / process.nexttick / MutationObserver 

微任务的执行优先级高于宏任务,每个宏任务执行完成后,都会清空微任务队列。

比如,我们执行一段script代码里面含有微任务,那这个执行过程是这样的。

首先,执行整体script代码,我们可以视为宏任务,执行过程中,如果遇到settimeout此类的宏任务就会把宏任务加入到任务执行队列中,遇到微任务则加入到微任务执行队列中。

然后,整体script宏任务执行完成后,就会开始执行微任务队列,如果这个过程中微任务又产生了微任务,则继续加到微任务队列的末位,直至整个微任务执行完成。

其次,微任务执行完成后,就开始UI线程的渲染。

最后,UI线程渲染完成后,js主线程又会继续到任务队列中取宏任务,重复上述步骤。

所以上述代码的执行结果是:1,4,7,5,8,2,3,6

相关文章

  • js线程执行原理

    众所周知,浏览器执行JS是单线程的,当然除了最新的worker线程,worker线程号称是浏览器端执行复杂运算一种...

  • JS异步之宏队列与微队列

    原理图 js单线程执行,首先执行主线程stack里面所有的代码,执行完成之后执行队列里面的函数。队列里面的函数优先...

  • 事件循环机制

    js是单线程的。浏览器: js执行线程:负责执行js代码 UI线程:负责UI展示,负责展示给用户看到的页面 js事...

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

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

  • javascript 异步操作会被阻塞吗?

    原文:http://icaoguo.com/?p=89 答案是会。 原理: js主线程发出异步请求之后会继续执行完...

  • 浏览器中的事件循环

    记忆核心: JS执行: 同步任务在JS主线程(属于渲染进程的线程)执行 异步任务进入任务队列(由事件触发线程维护)...

  • node面试题(一)

    一、node请求的原理? node.js使用的是单线程模型,对所有I/O都采用异步的请求方式。node.js在执行...

  • 浏览器中的事件循环与Node中的事件循环

    浏览器中的事件循环 JS线程读取并执行JS代码 执行JS代码的过程中,指定异步的操作给对应的线程处理 异步线程处理...

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

    继上一篇文章 JS引擎线程的执行过程的三个阶段(一) 三. 执行阶段 1. 网页的线程 永远只有JS引擎线程在执行...

  • 5-线程(补充)

    Python多线程原理与实战 目的: (1)了解python线程执行原理 (2)掌握多线程编程与线程同步 (3)了...

网友评论

      本文标题:js线程执行原理

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