-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
async/await在打包中的实现 #14
Comments
babel-runtime主要是引用了 core-js 和 regenerator,babel-helper主要引用babel的一些辅助函数 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
起源
为了在老工程中使用vue和react等,目前老项目使用rollup-to-nej这个工具打包。在观察打包生成后代代码的时候,发现有挺多的一些辅助函数,这些辅助函数会被重复的加入到我们打包生成的文件中,比如当我们使用async/await的时候。解决方法就是引入
babel-runtime
和babel-helper
并修改babel配置来移除这些辅助函数。当我比较修改之后的打包文件的时候,发现用到async/await的时候少了这么两个辅助函数。
那么到底打包的时候是如何实现async/await的呢?
实现
async/await实目前用的最多异步解决方案,它其实是Generator的一种语法糖,可以理解为一个自执行的generator。通常在babel或者ts打包为,一般会实现已下两步。
实现一个自执行的Generator
通常来说我们通过已下两种方式实现:
babel和ts在打包的时候都是使用co模块的思路通过Promise来实现,将已下测试代码在ts中转为es5
看完ts的实现,在去看babel的实现(如图1中所示),会发现他其实就是多拆分成了一个函数而已,实现方法都是相同的。
实现一个Generator生成器
因为因为Generator是es6的新语法,所以在babel和ts中打包为es5的代码时需要去实现一个Generator生成器。生成器的强大之处在于能方便地对生成器函数内部的逻辑进行控制。在生成器函数内部,通过
yield
或yield*
,将当前生成器函数的控制权移交给外部,外部通过调用生成器的next
或throw
或return
方法将控制权返还给生成器函数,并且还能够向其传递数据。生成器并非由引擎从底层提供额外的支持,我们可以将生成器视为一个语法糖,用一个辅助工具将生成器函数转换为普通的Javascript代码,在经过转换的代码中,有两个关键点,一是要保存函数的上下文信息,二是实现一个完善的迭代方法,使得多个
yield
表达式按序执行,从而实现生成器的特性。在babel中实现一个Generator
yield
被转换为switch case
,_context
保存着当前函数的上下文状态我们可以把
switch case
看做看做是一个状态机,根据_context
的状态来执行不同的代码。函数被
regeneratorRuntime.mark
包装,返回一个被regeneratorRuntime.wrap
包装的迭代器对象。简单来说,我们可以理解为实现了一个带有next\return\throw等属性的一个迭代器对象,babel中使用regenerator生成。如果了解regenerator的实现,可以看一下ES6 系列之 Babel 将 Generator 编译成了什么样子
我么也可以简单的看下ts中generator的实现。
它的实现也遵循了使用
switch case
来实现yield,_
来保存上下文状态。在__generator
函数中实现了一个迭代器对象,有着next,throw,return等方法。The text was updated successfully, but these errors were encountered: