图解 Google V8
李兵
前盛大创新院高级研究员
26763 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 25 讲
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

18 | 异步编程(一):V8是如何实现微任务的?

使用微任务技术
监视DOM树更改
使用setTimeout解决栈溢出
改变异步编程模型,允许使用同步形式的代码编写异步调用
解决实时性和效率之间的权衡
执行时机在主函数执行结束之后、当前宏任务结束之前
需要异步执行的函数
V8执行宏任务时重新创建栈
消息队列中等待主线程执行的事件
事件循环
消息队列
MutationObserver接口
宏任务、微任务的异步执行时机
调用栈、主线程、消息队列关联
循环触发微任务导致消息队列中其他任务无法执行
示例代码分析
微任务优先于宏任务执行
微任务在当前任务快要执行结束时执行
栈溢出问题
调用栈管理主线程上函数调用
微任务延伸出协程、Promise、Generator、await/async等技术
消息队列、事件循环、UI主线程、调用栈
微任务
宏任务
JavaScript运行在UI线程中
UI线程架构
思考题
总结
微任务中循环触发新的微任务
微任务解决宏任务执行时机不可控问题
主线程、调用栈、消息队列
微任务底层技术
V8实现微任务
异步编程

该思维导图由 AI 生成,仅供参考

你好,我是李兵。
上节我们介绍了通用的 UI 线程架构,每个 UI 线程都拥有一个消息队列,所有的待执行的事件都会被添加进消息队列中,UI 线程会按照一定规则,循环地取出消息队列中的事件,并执行事件。而 JavaScript 最初也是运行在 UI 线程中的。换句话说,JavaScript 语言就是基于这套通用的 UI 线程架构而设计的。
基于这套基础 UI 框架,JavaScript 又延伸出很多新的技术,其中应用最广泛的当属宏任务微任务
宏任务很简单,就是指消息队列中的等待被主线程执行的事件。每个宏任务在执行时,V8 都会重新创建栈,然后随着宏任务中函数调用,栈也随之变化,最终,当该宏任务执行结束时,整个栈又会被清空,接着主线程继续执行下一个宏任务。
微任务稍微复杂一点,其实你可以把微任务看成是一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前。
JavaScript 中之所以要引入微任务,主要是由于主线程执行消息队列中宏任务的时间颗粒度太粗了,无法胜任一些对精度和实时性要求较高的场景,那么微任务可以在实时性和效率之间做一个有效的权衡。另外使用微任务,可以改变我们现在的异步编程模型,使得我们可以使用同步形式的代码来编写异步调用。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

V8引擎中的微任务和宏任务机制是本文的重点。文章详细介绍了调用栈、消息队列和主线程的关系,以及栈溢出问题的解决方法。通过代码示例和图示,阐述了使用setTimeout将同步函数调用改成异步函数调用的过程,从而避免栈溢出。此外,文章还介绍了微任务的基本概念和其在异步编程模型中的重要作用,包括微任务的执行时机和微任务队列的管理方式。文章还探讨了在微任务中循环触发新的微任务可能导致的问题。通过本文,读者可以深入了解V8引擎中微任务的底层技术,以及微任务在异步编程模型中的重要作用。同时,文章提出了思考题,鼓励读者探索MutationObserver接口的工作原理,以及微任务在其中的作用。这篇文章对于想要深入了解V8引擎中微任务机制的读者来说是一份有价值的资料。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《图解 Google V8》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(39)

  • 最新
  • 精选
  • 3Spiders
    思考题,MutationObserver和IntersectionObserver两个性质应该差不多。我这里简称ob。ob是一个微任务,通过浏览器的requestIdleCallback,在浏览器每一帧的空闲时间执行ob监听的回调,该监听是不影响主线程的,但是回调会阻塞主线程。当然有一个限制,如果100ms内主线程一直处于未空闲状态,那会强制触发ob。

    作者回复: 研究的很细👍

    2020-04-26
    36
  • Shine
    微任务执行时,还是会在调用栈中创建对应函数的执行上下文吗?

    作者回复: 会的,和正常执行函数一样

    2020-04-28
    8
  • 王子晨
    老师我想问一下,如果说当前宏任务结束了,但是该宏任务中的微任务并没有被resolve(),比如请求接口,那这个微任务会延后到后面的宏任务中的微任务队列中么?

    作者回复: 没有resolve就意味着并没有产生微任务,在那个宏任务中resolve,就在那个宏任务中执行微任务

    2020-05-13
    2
    6
  • 天天
    setTimeout应该是由专门的定时器线程去管理吧,到点了才插入消息队列,然后等待消费

    作者回复: 不是的,setTimeout所产生的事件是由另外一个队列来管理的

    2020-04-26
    3
    5
  • zhangbao
    看的过程中,遇到两个疑问点,希望老师给予解答,谢谢! > 等微任务队列中的所有微任务都执行完成之后,当前的宏任务也就执行结束了 这里的“当前的宏任务”是指 调用栈 里的 全局执行上下文吗?“当前宏任务执行结束”是表示“从调用栈弹出全局执行上下文”的意思吗? > 微任务其实是一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前 文章中并没有对“主函数”的概念给予解释。可否把 主函数 理解成当前调用栈里最下面的那个执行上下文?微任务则是在最后的执行上下文弹出之前调用的,调用结束后,再执行消息队列里的宏任务?

    作者回复: 主线程有个消息循环系统,会不同从消息队列中取出宏任务,你可以把每个宏任务看成是一个函数,执行该宏任务的过程就是执行该函数的过程。 该函数直接结束,那么当前宏任务就执行结束了,那么消息循环系统会继续从消息队列中取出下个任务。 你可以把这里的主函数看成是宏任务的函数。

    2020-05-14
    2
    4
  • 零和幺
    像 setTimeout 、XMLHttpRequest 这种 web APIs,是浏览器的哪个部分提供的呢?它们并不是 V8 提供的,是浏览器内核么?提供这些 web APIs 的部分与 V8 又有什么关系?

    作者回复: 对,浏览器内核提供的,相当于宿主对V8的扩展

    2020-04-26
    4
    4
  • 孜孜
    微任务如果用到函数的变量,会产生闭包吗?

    作者回复: 会的

    2020-05-21
    3
  • 伏枫
    老师,哪些是宏任务,哪些是微任务?

    作者回复: 通过promise 的resolve、reject等方法产生的是微任务,如果使用了mutationobserver,使用js修改dom元素也会产生微任务。 其他的定时器,各种事件都是宏任务

    2020-04-26
    4
    3
  • 大力
    感悟: 1. 微任务的执行时机有点类似 NodeJS 中beforeExit 事件的执行时机; 2. 微任务会有可能造成 UI 线程阻塞,而异步回调函数构成的宏任务则不会,这样看来回调函数在这一点上要比 promise 优胜?

    作者回复: 理解的很透彻

    2020-04-30
    2
  • 子云
    老师,我有个疑问,fs.readFileSync 是怎么回事,它怎么就做到同步调用了,看起来也不像是 readFile 的语法糖呀?那么它有事件循环机制吗,不太可能真的是 JS 的主线程去读文件吧?

    作者回复: 就是同步实现的,在主线程里面执行的

    2020-06-04
    1
收起评论
显示
设置
留言
39
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部