美文网首页
JavaScript事件循环

JavaScript事件循环

作者: 刷题刷到手抽筋 | 来源:发表于2022-05-24 08:00 被阅读0次

    单线程和异步

    为什么JavaScript引擎是单线程的?为什么JavaScript要引入异步编程?这些都是老生常谈,不做赘述。值得说明的是,js的事件循环正是用来实现异步特性的。

    事件循环概述

    js的执行机制就是事件循环。js在执行时,有以下几个主要部分参与了事件循环。

    1. 执行栈,用来创建执行环境,执行js代码
    2. 异步处理模块,用来处理异步事件
    3. 任务队列,包括宏任务队列和微任务队列,用来控制消息的生产消费

    事件循环的过程为:当执行栈空的时候,就会从任务队列中,取任务来执行。共分3步:

    1. 取一个宏任务来执行。执行完毕后,下一步。
    2. 取一个微任务来执行,执行完毕后,再取一个微任务来执行。直到微任务队列为空,执行下一步。
    3. 更新UI渲染。

    其中,UI渲染会根据浏览器的逻辑,决定要不要马上执行更新,不一定在本次循环中立即执行。可以看到,事件循环中包含UI渲染,这就是为什么我们说js的执行会阻塞UI渲染。

    任务队列

    任务队列里保存的,是事件的回调函数,异步处理模块就负责将异步事件回调插入到任务队列中。比如,定时器模块执行setTimeout方法后,会在计时结束后,将回调函数加入到相应的宏任务队列中去。

    宏任务队列和微任务队列

    1. 宏任务队列可以有多个,微任务队列只有一个
    2. 宏任务有 script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering。微任务有 process.nextTick, Promise, Object.observer, MutationObserver。
    3. 宏任务队列有优先级之分。每次js引擎从宏任务队列中取宏任务时,会按照优先级选择宏任务队列,若高优先级的宏任务队列中没有任务时,才会到低级的宏任务队列中去取任务。
    4. 为什么会有宏任务和微任务之分呢?个人理解,宏任务才是真正意义上的任务,而微任务相当于宏任务的附属的一系列操作和相应。所以,js引擎每次取出一个宏任务执行,并且执行相关的微任务,这样保证一个完整的任务被执行完。这也是微任务队列只有一个的原因,微任务队列就是用来辅助宏任务队列的任务的完整执行的。而宏任务队列才是真正意义的任务,任务有优先级之分就很好理解了,因此才有多个宏任务队列,就是为了区分优先级。

    执行过程

    首先,js引擎从宏任务队列中取任务,因为script(全局)宏任务队列的优先级最高,因此先将这个任务取出(这个任务是当前所有可执行脚本),并利用执行栈执行这些脚本。在执行过程中,会产生一些异步操作,将之交由异步处理模块处理。异步处理模块会产生一系列异步回调,加入到任务队列中。当前执行栈执行完(栈为空)时,再执行微任务队列中的所有任务。执行完后,再从根据优先级从宏任务队列中取出一个任务执行,然后再从微任务队列中取任务执行直到微任务队列为空。 就这样循环往复,生生不息。

    相关文章

      网友评论

          本文标题:JavaScript事件循环

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