co模块的实现原理的理解

co模块是koa框架实现的关键技术,主要解决的是node.js的回调函数嵌套过多的问题。
它用到了ES6的新特性generator函数, promise技术,以及thunk函数。

回调地狱问题:异步函数因为其结束时间的不确定性,只能在其回调函数中处理其产生的数据。
因此多个异步函数结果需要顺序执行时候,就只能通过回调函数一步步的嵌套执行,造成代码可读性很差。

我的几点理解:

1.generator函数可以将函数分段执行,执行每段后交出控制权,只有下次next才会继续执行。然而实际上它的yield与next方法都是同步的,连续next的话,被yield的异步函数并不会同步执行。
用generator函数解决回调地狱的方法是,把next写在上一个异步操作的回调函数里,从而使操作同步。

2.promise技术是一个包装了一些方法的语法糖。因为每次then中resovle函数被调用的时机,就是普通写法中回调函数被调用的时机,没什么本质区别。
它的好处是,把回调函数的嵌套换成了连续then的表示形式,没有了嵌套可读性好了很多,异常处理更简单清晰。

3.thunk函数语法糖都不算,只是将函数转化了下格式。 将A形式的function(paras) 转化成B形式的function(callback) paras inside,
这样调用时候,用户使用A形式,直接传参数给方法;而co模块使用B形式,传入自己的callback来控制函数执行的顺序,进行流程管理。
它的好处是,把函数和参数包装在一起给co当作函数参数使用,而不是立刻执行。

简易版co函数的实现原理

//co核心实现
function co(generator) {
return function(finishCallback) {           //co的callback函数
var gen = generator();                  //获得generator指针对象
nextStep();                             //通过异步函数的callback实现nextStep的递归调用
 
function nextStep(err, result) {
             if (err) return finishCallback(err);
 
             var step = gen.next(result);            //执行一步next
             if (!step.done) step.value(nextStep);   //没yield完,执行该异步函数,并且将nexStep作为其callback递归调用
             else finishCallback( null , step.value);  //yield完了,终止
         }
}
}
//模拟的异步操作
function async(data) {
     return function(callback){
         setTimeout(function () {
             console.log( 'async done: ' +data);
             callback();
         }, 2000 );
     }
}
 
//流程控制函数
var gen = function *generator(){
     console.log( "start" );
     var a=yield async( "async 1" );
     var b=yield async( "async 2" );
     return "finish" ;
}
 
//同步执行流程
var coo=co(gen);
coo(function(err,data){
     if (err != null )console.log(err);
     else console.log(data);
});

输出:
start
async done: async 1
async done: async 2
finish

可以观察到两个异步操作分别等待了2s,说明他们之间是同步执行的。
代码比较清楚,就是每一步yield出来一个异步方法,然后将nextStep方法作为回调函数传给该异步方法 ; 递归执行nextStep方法,直到返回的结果done属性为真。
实际的co模块采用promise实现,原理和简易版没什么区别。

使用co模块方法

co=require( 'co' );
 
//模拟的异步操作
function async(data) {
     return function(callback){
         setTimeout(function () {
             console.log( 'async done: ' +data);
             callback();
         }, 2000 );
     }
}
//流程控制函数
var gen = function *generator(){
     console.log( "start" );
     var a=yield async( "async 1" );
     var b=yield async( "async 2" );
     return "finish" ;
}
 
 
//同步执行流程
co(gen).then(function(data){
     console.log(data);
},function(err){
     console.log(err);
});

输出:

start
async done: async 1
async done: async 2
finish

输出与上面一样,同样可以观察到时间等待,说明同步成功了。

参考:http://es6.ruanyifeng.com/#docs/async

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值