co 源码精读

co是TJ于2013年推出的开源项目,利用ES6的Generator函数解决异步操作,是async/await的先驱。只需将Generator函数传给co(),即可编写类似同步的异步代码。本文详细解析了co的实现原理,包括如何使用Promise自动执行异步代码。

原文链接:http://chriscindy.top/post/the-analysis-of-the-source-code-of-co/

co 是著名的 TJ 于 2013 年推出的一个利用 ES6 的 Generator 函数来解决异步操作的开源项目,也是后来 JavaScript 异步操作的终极解决方案—— async/await 的先驱。时至今日,co 版本号已经来到了 4.x,不过其代码仍然只有寥寥数百行,十分适合阅读与学习。下面我们就来看一下 co 是如何对异步操作进行处理的。

首先先来看一下 co 的基本用法。co 使用起来十分方便,只需要将一个 Generator 函数作为参数传给 co(),就能在该函数中像同步代码一样编写异步代码。看一下官方示例:


第 9 行的函数体中,a、b、c 的值都是异步返回的,但是却可以像同步一样调用。这便是 co 的魔力。

除此之外,co 还提供了一个 API—— co.wrap() ,用于将被 co 包裹的 generator 函数转换成为一个返回 promise 的普通函数,示例如下:

了解完了 API,我们就可以来看一下 co 内部的实现原理。下面是经过笔者注解(中文注释)的源码:





我们可以看到,co 的核心逻辑在于第 90 行的 next 函数,这里将每一次 yield 的返回值包装成 Promise 对象,在 Promise 的 onFulfilled 和 onRejected 状态中继续递归调用 next 函数,保证链式调用自动执行,使得异步的代码能够以同步的方式运行。

可能还有读者有疑问,如果不借助 Promise,这样的链式自动执行是否还可以实现。事实上,在 co 的 4.0.0 版本以前,其底层实现就没有借助 Promise,而是采用了 Thunk 函数的方式。感兴趣的读者可以切换到 3.1.0 版本学习源码。

注:如有关于什么是 Thunk 函数的疑问,点击这里

阮一峰老师在《ECMAScript 6 入门》一书中对于 Generator 函数自动执行的原理有一个精准的结论:“自动执行的关键是,必须有一种机制,自动控制 Generator 函数的流程,接收和交还程序的执行权。回调函数可以做到这一点,Promise 对象也可以做到这一点。”我们还是以 Promise 对象为例解释一下这句话:将通过 yield 返回的对象的 value 保持为一个 Promise 对象,执行之,即可拿到程序的执行权。然后通过 Promise.then 和 Promise.reject 方法中调用 generator 的 next 方法,可以交还程序执行权。如此达到自动执行 generator 函数的效果。

最后,感谢 co 这样的优秀项目作为开拓者,才有了后来的 async/await ,让 JavaScript 开发人员不再因为这门语言独特的单线程特性而深陷异步编程带来的困扰。


转载于:https://juejin.im/post/59e948fe6fb9a0450c48868b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值