图解js中的EventLoop

Posted 前端鸡腿哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图解js中的EventLoop相关的知识,希望对你有一定的参考价值。

前置概念:

  • javascript 是单线程的

  • JS线程和UI线程是一对互斥线程, 当JS引擎线程执行时GUI渲染线程会被挂起,GUI更新则会被保存在一个队列中等待JS引擎线程空闲时立即被执行。

  • 执行栈

    • 定义:存储函数调用的栈结构,即执行宏任务的栈

    • 原则:先进后出。即先执行的函数后销毁,如图

    • 分析:以具体函数的执行为单位,每执行到一个函数就入栈一个函数,直到最后入栈的函数执行完,依次倒退执行,执行完就出栈。总结下来就是:函数开始执行时入栈,执行完出栈,遵循先进后出的顺序。

  • 从整体上看,事件队列分为宏任务微任务

  • 同步任务与异步任务同属于宏任务

  • 异步事件队列

    • 定义:一个用来存放异步任务的回调函数的栈

    • 作用:当一个异步任务的触发条件达成时,回调函数会被存放入事件队列中。当执行栈中的同步任务执行完毕后,开始执行事件队列中已经存放的异步任务的回调函数

  • 微任务事件队列

    • 定义:一个用来存放微任务的栈

    • 作用:当宏任务全部执行完毕的时候,就会立马执行微任务事件队列中的微任务

EventLoop具体解析

js的宏任务分为同步任务和异步任务,同步任务都在JS引擎线程上执行,形成一个执行栈,事件触发线程管理一个事件队列,异步任务触发条件达成,将回调事件放到事件队列中,执行栈中所有同步任务执行完毕,此时JS引擎线程空闲,系统会读取事件队列,将可运行的异步任务回调事件添加到执行栈中,开始执行。具体如下图所示:

图解js中的EventLoop

EventLoop中的宏任务与微任务

  • 宏任务:我们可以将每次执行栈执行的代码当做是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行), 每一个宏任务会从头到尾执行完毕,不会执行其他。GUI渲染线程会穿插各个宏任务的执行间隔之间执行.主代码块,setTimeout,setInterval等,都属于宏任务

  • 微任务:穿插在宏任务与GUI渲染线程执行间隙间执行的任务。Promise,process.nextTick等,属于微任务

宏任务-->微任务-->渲染-->宏任务-->微任务-->-->渲染...

· 执行一个宏任务(栈中没有就从事件队列中获取)
· 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
· 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
· 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
· 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

注:微任务的优先级是高于渲染的,promise的then是微任务,但是微任务是有任务队列的,异步执行完promise的then才会添加到微任务队列,所以如果异步没有执行完会直接执行下一个宏任务。


以上是关于图解js中的EventLoop的主要内容,如果未能解决你的问题,请参考以下文章

图解 | 4道题带你初步了解浏览器的EventLoop

前端中的事件循环eventloop机制

图解搞懂JavaScript引擎Event Loop

搞懂js中 eventloop事件循环和Promise面试题

JS基础--EventLoop

详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务