JS事件循环——宏任务与微任务执行顺序

最近被事件循环搞蒙了,写一篇来巩固一下,下面这段代码输出顺序是什么:

import { nextTick } from 'vue'

new Promise((resolve, reject) => {
  console.log(1)
  resolve(2)
  console.log(3)
}).then(val => {
  console.log(val)
})

setTimeout(() => {
  console.log(4)
  nextTick(() => {
    console.log(5)
  })
  console.log(6)
}, 0); 

nextTick(() => {
  console.log(7)
})

console.log(8)

输出顺序是1,3,8,2,7,4,6,5,这个答案得从js事件循环开始说。

JS的事件循环机制

事件循环(vent Loops)用于协调事件、用户交互、JavaScript 脚本、DOM 渲染、网络请求等等的执行顺序问题。

一个遵循 ECMAScript 标准的代理(浏览器或 JS 引擎)也必须遵循事件循环机制。

事件循环是由一个或以上的 任务队列 组成的。

任务队列

任务队列(Task Queues),是一组任务的集合(Sets)。由于 JavaScript 是 单线程 语言,所以在 JS 中所有的任务都需要排队执行,这些任务共同组成了 任务队列,依次排队执行的过程,形成一个 执行栈(Execution Context Stack)

在任务队列中最先执行是同步任务,这个就是按代码循序从上到下执行(本文不讨论关于变量提升之类的问题)。本文主要讨论异步任务的执行在任务队列里的执行情况。

异步任务

异步任务(Asynchronous Task)是需要等待被通知才以执行的任务。也就是说,它们不会直接进入主线程执行,而是进入到微任务队列或下一次事件循环中的任务队列进行等待。异步任务被分为宏任务和微任务来拆分不同的执行时刻和返回时刻。

宏任务

  • 主代码块:JavaScript中的主线程代码。
  • setTimeout和setInterval:定时器任务。
  • I/O操作:例如文件读写、网络请求等。
  • UI渲染:浏览器需要重绘或者重新布局的任务,包括 DOM 解析、CSS 解析、页面布局和绘制等与页面渲染相关的任务。。
  • 用户交互事件:例如点击、滚动、输入等用户操作触发的事件。
  • requestAnimationFrame:用于执行动画效果的任务。

微任务

  • Promise回调函数:Promise对象的处理程序(then、catch、finally)。
  • MutationObserver:监测DOM变化的任务。
  • process.nextTick(Node.js环境下):在当前"执行栈"结束后立即执行的任务。
  • queueMicrotask():用于将一个微任务添加到微任务队列中。

上面这些就只能靠死记硬背了

宏任务与微任务的执行顺序

在事件循环(Event Loop)中,当主线程空闲时,会从宏任务队列中选择一个任务进行执行。当一个宏任务执行完毕后,会检查是否有微任务队列,如果有,则将微任务队列中的所有任务依次执行完毕,然后再继续选择下一个宏任务执行。这样的过程循环进行,形成了事件循环。

总结来说,宏任务代表着较大粒度的任务,而微任务代表着较小粒度的任务。微任务通常在宏任务执行完毕后立即执行,因此微任务具有更高的优先级,可以在页面渲染前执行,从而提供更好的用户体验。

好,现在我们再回到题目本身

  1. 首先将代码宏任务和微任务分好,遇到Promise本身块里的属于宏任务。Promise.then放入微任务队列。(打印1,3)
  2. 遇到settimeout宏任务,但是延时了,所以要等微任务执行完才执行。
  3. 遇到nextTick,放入微任务队列。
  4. 遇到console.log(),宏任务直接打印。(打印8)
  5. 此时主线程空闲,接下来就是先执行微任务队列里的,首先是Promise.then。(打印2)
  6. 然后是nextTick,至此微任务执行完毕。(打印7)
  7. 微任务执行完毕后,延时的宏任务settimeout开始执行,遇到console.log,宏任务直接打印。(打印4)
  8. 遇到nextTick,放入微任务队列。
  9. 遇到console.log,宏任务直接打印。(打印6)
  10. 此时主线程空闲,微任务队列里还有个nextTick,直接打印。执行完毕。(打印5)

图文的等有空闲再上传。

posted @   honoka_Gu  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示