图解 Google V8
李兵
前盛大创新院高级研究员
立即订阅
3761 人已学习
课程目录
已完结 25 讲
0/4登录后,你可以任选4讲全文学习。
宏观视角 (2讲)
开篇词 | 如何学习谷歌高性能 JavaScript 引擎V8?
免费
01 | V8是如何执行一段JavaScript代码的?
JavaScript设计思想篇 (7讲)
02 | 函数即对象:一篇文章彻底搞懂JavaScript的函数特点
03 | 快属性和慢属性:V8是怎样提升对象属性访问速度的?
04 | 函数表达式:涉及大量概念,函数表达式到底该怎么学?
05|原型链:V8是如何实现对象继承的?
06|作用域链:V8是如何查找变量的?
07|类型转换:V8是怎么实现1+“2”的?
08|答疑:如何构建和使用V8的调试工具d8?
V8编译流水线 (8讲)
09 | 运行时环境:运行JavaScript代码的基石
10 | 机器代码:二进制机器码究竟是如何被CPU执行的?
11 | 堆和栈:函数调用是如何影响到内存布局的?
12 | 延迟解析:V8是如何实现闭包的?
13 | 字节码(一):V8为什么又重新引入字节码?
14|字节码(二):解释器是如何解释执行字节码的?
15 | 隐藏类:如何在内存中快速查找对象属性?
16 | 答疑: V8是怎么通过内联缓存来提升函数执行效率的?
事件循环和垃圾回收 (6讲)
17 | 消息队列:V8是怎么实现回调函数的?
18 | 异步编程(一):V8是如何实现微任务的?
19|异步编程(二):V8是如何实现async/await的?
20 | 垃圾回收(一):V8的两个垃圾回收器是如何工作的?
21 | 垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
22|答疑:几种常见内存问题的解决策略
结束语 (2讲)
结束语 | 我的前端学习踩坑史
结课测试 | 这些V8的知识你都掌握了吗?
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

19|异步编程(二):V8是如何实现async/await的?

李兵 2020-04-28
你好,我是李兵。
上一节我们介绍了 JavaScript 是基于单线程设计的,最终造成了 JavaScript 中出现大量回调的场景。当 JavaScript 中有大量的异步操作时,会降低代码的可读性, 其中最容易造成的就是回调地狱的问题。
JavaScript 社区探索并推出了一系列的方案,从“Promise 加 then”到“generator 加 co”方案,再到最近推出“终极”的 async/await 方案,完美地解决了回调地狱所造成的问题。
今天我们就来分析下回调地狱问题是如何被一步步解决的,在这个过程中,你也就理解了 V8 实现 async/await 的机制。

什么是回调地狱?

我们先来看什么是回调地狱。
假设你们老板给了你一个小需求,要求你从网络获取某个用户的用户名,获取用户名称的步骤是先通过一个 id_url 来获取用户 ID,然后再使用获取到的用户 ID 作为另外一个 name_url 的参数,以获取用户名。
我做了两个 DEMO URL,如下所示:
const id_url = 'https://raw.githubusercontent.com/binaryacademy/geektime-v8/master/id'
const name_url = 'https://raw.githubusercontent.com/binaryacademy/geektime-v8/master/name'
那么你会怎么实现这个小小的需求呢?
其中最容易想到的方案是使用 XMLHttpRequest,并按照前后顺序异步请求这两个 URL。具体地讲,你可以先定义一个 GetUrlContent 函数,这个函数负责封装 XMLHttpRequest 来下载 URL 文件内容,由于下载过程是异步执行的,所以需要通过回调函数来触发返回结果。那么我们需要给 GetUrlContent 传递一个回调函数 result_callback,来触发异步下载的结果。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《图解 Google V8》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(14)

  • 若川 置顶
    co源码实现原理:其实就是通过不断的调用generator函数的next()函数,来达到自动执行generator函数的效果(类似async、await函数的自动自行)。

    具体代码分析,我之前写过一篇文章:
    《学习 koa 源码的整体架构,浅析koa洋葱模型原理和co原理》
    https://juejin.im/entry/5e6a080af265da575b1bd160

    作者回复: 赞,高手

    2020-05-02
    5
  • HoSalt
    老师 async、await 是 generator promise 的语法糖吗,v8里面前者是借助后者实现的吗?async await 为什么能用try catch 捕获错误?

    作者回复: async/await可以不是语法糖,而是从设计到开发都是一套完整的体系,只不过使用了协程和promise!
    支持try catch也是引擎的底层来实现的

    2020-04-29
    4
  • 潇潇雨歇
    co的原理是自动识别生成器代码的yield,做暂停执行和恢复执行的操作

    作者回复: 没问题

    2020-04-28
    3
  • 蹦哒
    请教老师:为什么Generator方案不实现自动执行next的功能呢?我理解async/await相对于Generator方案主要是能够自动执行next吧,co方案也是这么做的

    作者回复: 如果自动执行了,那么就是await了,之所以没有这样实现,我想是因为技术在迭代发展吧,完美的技术总是很难一步到位

    2020-05-12
    2
    2
  • Aaaaaaaaaaayou
    co 里面一般会定义一个方法,比如nextStep,执行改方法时会调用迭代器的next,根据结果中的done的取值来决定是继续递归调用nextStep还是结束。
    2020-04-28
    2
  • Geek_gaoqin
    哦,我知道了,async 修饰的函数会有自己的协程,那么它代码内部创建的宏任务,主线程有空了还是会拿消息队列中的宏任务来执行,如果await等待了一个never resolve,那么它后面的代码就再也不会执行!但是却不会影响消息队列中键盘鼠标事件等其它任务的执行!

    作者回复: 是这样的

    2020-06-11
    1
  • Geek_gaoqin
    老师,很长很长一段代码中,业务逻辑很复杂,既有产生微任务,又有setTimeout产生宏任务,更有很多await的语句,那么这些结合上一章节讲的内容,它的执行顺序是怎样的呢?可以帮我分析下吗?

    作者回复: 微任务先执行,settimeout后执行,await可以跨越多个宏任务

    2020-06-11
  • Presbyter🎱
    老师,我如果想在一个async内同时执行多个await操作,这个应该怎么处理呢
    2020-06-11
  • 断线人偶
    老师可以讲一下为什么在使用async...await...可以通过try...catch...来捕获到异步函数中的异常吗,v8是怎么实现的

    作者回复: 这个是V8实现的,比如触发了reject的时候,v8就会跳转到catch

    2020-05-24
  • 华仔
    setTimeout(() => {
    console.log('in timeout');
    })
    new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve(3);
    console.log('in promise-timeout')
    })
    console.log('in promise')
    }).then((res) => {
    console.log('in then')
    })
    老师,想问下promise创建的then是微任务,是宏任务中创建的队列保存的消息队列中维护的。那么我这里这样一个场景,在promise中通过setTimeout(模拟宏任务http request)异步resolve的场景下,then也就会在下一个宏任务执行之后再执行了。这种当前宏任务中注册的微任务被拖到下一个宏任务执行,是怎么实现的呢?

    作者回复: 微任务是在reslove时生成的,你创建一个peomise并不会立马产生一个微任务,而是要等到resolve或者reject时,才会触发微任务,在那个宏任务中触发了微任务,微任务就在该宏任务快要执行结束之后执行,无论你promise是在拿个宏任务中创建的!

    2020-05-05
    3
  • 地球外地人
    老师能讲讲 generate 和 await async中的闭包吗?

    作者回复: 闭包的实现原理都是一样的,你可以列出具体问题,我来给你回答,最好新开一个回复,这样我更容易看到

    2020-05-04
  • 天然呆

    function HaveResolvePromise(){
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(100)
              }, 0);
          })
    }
    async function getResult() {
        console.log(1)
        let a = await NoResolvePromise()
        console.log(a)
        console.log(2)
    }
    console.log(0)
    getResult()
    console.log(3)

    是不是要改动?NoResolvePromise ==>> HaveResolvePromise

    作者回复: 嗯 改过来了

    2020-04-28
  • Geek_f74777
    看来一下co源码, 我的理解是: co的执行原理就是通过promise将generator函数中yield的异步操作的暂停和恢复执行自动化

    作者回复: 是的

    2020-04-28
  • 写点啥呢
    async/await章节的示例代码看着迷糊了,想和老师请教下,
    1. 这部分代码,foo是不是应该调用getResult

    function NeverResolvePromise(){
        return new Promise((resolve, reject) => {})
    }
    async function getResult() {
        let a = await NeverResolvePromise()
        console.log(a)
    }
    foo()
    console.log(0)

    2. 在这个代码片段里,foo函数内await的应该是HasResolvePromise

    function HaveResolvePromise(){
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(100)
              }, 0);
          })
    }
    async function foo() {
        console.log(1)
        let a = await NoResolvePromise()
        console.log(a)
        console.log(2)
    }
    console.log(0)
    foo()
    console.log(3)

    另外#2问题里的代码对应的图例中的函数名字和代码对应不上。

    作者回复: foo写错了,是getResult,我马上改正下正文

    2020-04-28
收起评论
14
返回
顶部