浏览器事件循环机制以及同异步理解

首先介绍几个相关的概念

  • 执行栈

    我们知道执行栈会存储和管理代码执行过程中的执行上下文,通过频繁的入栈退栈操作执行上下文,并执行每个执行上下文内部的代码。常规的同步代码就是这样执行的。

    那么异步代码怎么执行呢?首先我们明确一个概念:任务源。什么是任务源?比如我们在同步代码中开启一个定时器setTimeOut,这个setTimeOut就是任务源,setTimeOut内部会传入回调函数,这个回调函数即为要执行的异步代码

    执行栈在遇到任务源时,不会像执行同步代码那样直接执行它的回调函数,而是会将异步代码添加任务队列中。

  • 任务队列

    上面我们提到了任务队列是用来存放异步代码的容器。任务队列根据其存放异步代码的类型可以分为两种,宏任务队列微任务队列,分别用来存放宏任务微任务

  • 宏任务&微任务

    一段异步代码属于宏任务还是微任务其实是由任务源决定的。

    常见的宏任务:setTimeout、setInterval、requestAnimationFrame内部的回调、script(整体代码)

    常见的微任务:promise.then中的回调,nextTick中传入的回调,MutationObserver

事件循环机制流程

  1. 主线程生成执行栈开始执行一段代码,同步代码优先执行,执行过程中遇到任务源时,判断这个任务源是宏任务源还是微任务源。
  2. 如果是宏任务源,将其内部宏任务添加到宏任务队列中,如果是微任务源,将其内部微任务添加到微任务队列
  3. 等同步代码执行完毕,执行栈进入闲置状态,检查微任务队列中是否有微任务,如果有,执行栈会依次执行这些微任务。
  4. 渲染UI
  5. 检查宏任务队列中是否有宏任务,如果有,取出宏任务队列中最前面的那个宏任务,推入到执行栈中开始执行。执行完毕后重复步骤3-5直到宏任务队列和微任务队列全部清空

注意:

根据上面的流程,我们知道如果一段同步代码中同时有一个宏任务源和一个微任务源,那么微任务一定会比宏任务先执行

每次执行栈在访问微任务队列时,会将当前微任务队列清空,但访问宏任务队列时,只会执行队列最上方的宏任务

猜你喜欢

转载自blog.csdn.net/m0_64023259/article/details/126159013
今日推荐