co & thunkify
co
之前在generator中已经介绍过Co了
co一般和thunkify一起使用 能够使得generator用起来更方便 所以co就是一个generator的流程控制模块
以fs.readFile作为例子
先把readFile thunkify一下
从
fs.readFile(filename, callback)
变成
readThunk(filename)(callback)
这样的调用形式
co的用法
co(function* (){
var fs1 = yield readThunk('a.txt', 'utf8');
var fs2 = yield readThunk('b.txt', 'utf8');
//...
})
你可以像Async那样用同步的方式书写异步代码
这里的fs1 fs2就是 a.txt b.txt文件中的内容
真奇怪 fs1 fs2 的值应该是由 gen.next() 传入啊,
难道说 gen.next() 传入了 readThunk得到的文件内容?
没错 就是这样
下面简单说说co的源码
function co(gen) {
var ctx = this;
var args = slice.call(arguments, 1)
return new Promise(function(resolve, reject) {
gen = gen.apply(ctx, args);
//onFulfilled实际上调用第一个gen.next();
onFulfilled();
//为了能够这样调用 var a = yield asyncFuntion();
//那么就需要将前一个async的返回值通过 gen.next()传给 变量a
//也就是将res这个值给a
function onFulfilled(res) {
var ret;
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
}
function onRejected(err) { ... }
function next(ret) {
if (ret.done) return resolve(ret.value);
//将异步函数转为一个Promise对象 value是一个Promise对象
var value = toPromise.call(ctx, ret.value);
//判断是否是一个Promise对象 就是看是否有then()
if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
}
});
}
可见用一个Promise 来处理异步函数 将异步函数readFile的结果通过Filfilled这个callback再次调用gen.next() 所以fs1 fs2 就是文件内容
不过即使thunkify之后 至始至终貌似都只向 readThunk传了一个参数 callback呢?
仔细研究就会发现一般的回调函数都是 function(err, data)的形式 所以co在
thunkToPromise 中用一个通用的回调函数 不用自己写回调函数了
这个回调函数就是将 data resolve 并返回一个Promise
fn就是异步函数
return new Promise(function (resolve, reject) {
fn.call(ctx, function (err, res) {
if (err) return reject(err);
if (arguments.length > 2) res = slice.call(arguments, 1);
resolve(res);
});
});
Promise success的那部分调用 Fulfilled 也就是再次调用了gen.next
co基本的处理流程就是这样
co & thunkify的更多相关文章
- node的 thunkify模块说明
thunkify这种函数其实就是python的decorator方式,对目标方法进行一步步的wrap,但是这种方式和generator结合起来就会威力无穷了,实现自动异步功能. thunkify使用一 ...
- thunkify和co的邂逅
上一篇说到thunkify的作用,这一篇说一下thunkify和co的集合 co中有一块代码 /** * Convert a thunk to a promise. * * @param {Funct ...
- thunkify 模块
function thunkify(fn){ assert('function' == typeof fn, 'function required'); return function(){ var ...
- node中的流程控制中,co,thunkify为什么return callback()可以做到流程控制?
前言 我在学习generator ,yield ,co,thunkify的时候,有许多费解的地方,经过了许多的实践,也慢慢学会用,慢慢的理解,前一阵子有个其他项目的同事过来我们项目组学习node,发现 ...
- PHP下的异步尝试三:协程的PHP版thunkify自动执行器
PHP下的异步尝试系列 如果你还不太了解PHP下的生成器和协程,你可以根据下面目录翻阅 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunk ...
- 深入解析js异步编程利器Generator
我们在编写Nodejs程序时,经常会用到回调函数,在一个操作执行完成之后对返回的数据进行处理,我简单的理解它为异步编程. 如果操作很多,那么回调的嵌套就会必不可少,那么如果操作非常多,那么回调的嵌套就 ...
- node.js Stream Buffer FsPromise
Stream: 类似这样:a.pipe(b).pipe(c); 我想写一个b.所以: var rs=new (require('stream').Readable)(); var ws=new (re ...
- 如何优雅的处理Nodejs中的异步回调
前言 Nodejs最大的亮点就在于事件驱动, 非阻塞I/O 模型,这使得Nodejs具有很强的并发处理能力,非常适合编写网络应用.在Nodejs中大部分的I/O操作几乎都是异步的,也就是我们处理I/O ...
- 转: ES6异步编程:Thunk函数的含义与用法
转: ES6异步编程:Thunk函数的含义与用法 参数的求值策略 Thunk函数早在上个世纪60年代就诞生了. 那时,编程语言刚刚起步,计算机学家还在研究,编译器怎么写比较好.一个争论的焦点是&quo ...
随机推荐
- Android 使用BroadcastReceiver的几种方法
发送自定义广播 全局广播 发送标准广播 1.定义广播接收器.(在发送广播前,需要先定义一个广播接收器,不然发了也是白发) public class MyBroadcastReceiver extend ...
- STM32F051关于printf函数在串口打印中的使用
1.需要在Options for Target -> Code Generation 中勾选Use MicroLIB: 2.需要加入下面这个函数: int fputc(int ch, FILE ...
- SqlServer取得一个月的所有有日期
SqlServer的自定义函数可以分为三类但我只用过上面两类,可以称作标量函数和表值函数,区别只是返回数据的类型,表值函数返回的是一个虚拟表 SqlServer的函数在这里 因某种需求我写了一个这样的 ...
- Oracle EBS-SQL (OM-4):检查发运网络.sql
select msn.FROM_ORGANIZATION_CODE 开始库存组织, msn.FROM_ORGANIZATION_NAME 开始库存名称, ...
- android的edittext输入长度
http://blog.csdn.net/uyu2yiyi/article/details/6329738 http://flysnow.iteye.com/blog/828415/ http://s ...
- git 拉取远程分之到本地
git checkout -b newbranch_name --track origin/feature/newbranch_name 如果遇到类似: fatal: git checkout: up ...
- 常用的wsdl地址
天气预报Web Service,数据来源于中国气象局 Endpoint Disco WSDL IP地址来源搜索Web Service(是目前最完整的IP地址数据) Endpoint Disco WSD ...
- HDU2084 数塔 (DP入门题)
数塔 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...
- spring 定时任务(3)--配置多个定时任务
<!-- 定义调用对象和调用对象的方法 --> <!-- 定时任务 A start --> <bean id="jobtask" class=&quo ...
- C++匈牙利命名法
匈牙利命名法 匈牙利命名法是一种编程时的命名规范.基本原则是:变量名=属性+类型+对象描述,其中每一对象的名称都要求有明确含义,可以取对象名字全称或名字的一部分.命名要基于容易记忆容易理解的原则.保证 ...