Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all articles
Browse latest Browse all 14821

跟co类似,但有一点点golang的感觉

$
0
0

要说什么啊: 一个和 co类似的模块,带点golang的感觉。

哦,原来是造轮子啊? 哎呀,客官,别急,简单看看呗,绝对大有不同 ^_^

发这儿干嘛: 分享,然后求意见。正是由于身边人的建议,更新到了现在的版本。

talk is cheap,show me the code

好,代码来了

defer

defer 这个功能借鉴至golang的defer 关键字,执行逻辑也一样,在将要退出时执行绑定的操作.

const co = require("zco");
const request = require("request");

co(function*(next,defer) {  
	defer(function*(inner_next,error) {
	    if(error) {
		   console.log(error.message);//"模拟一下未知的错误" ,这个错误是后面手动throw模拟的
		}
		//做些清理工作,案例:个人在一个有热更新需求的项目中需要确保释放了模块的引用,并且无论之后的代码是否报错.
	});
	let [err,response,body]=yield request("www.baidu.com",next);//异步请求百度首页,与request模块无缝对接
	//..... do something else
	throw new Error("模拟一下未知的错误");
})();

inner_next功能和外部的next 一致,error是捕获的defer之后的代码抛出的异常。

超时终止协程

某些场景会设置最大等待时间,个人是做爬虫工作的,一些破网站经常超时,希望在超时时终止协程,不再继续往后执行。

到截止时间,还没有执行的操作就没有任何执行的意义了,应该尽早终止,这样避免了没有必要的资源消耗(内存,CPU,带宽…)。 需要注意的是 defer定义的操作在挂起协程时会执行.

来个栗子:


const co=require("zco");

let variable=1;
//先伪造一个耗时操作
const I_need_more_time=function(){
    return co(function*(next){
         variable+=100;//加100
		 yield setTimeout(next,2*100);//等待200毫秒,模拟耗时操作
		 variable+=1000;//加1000
	})
}
//期望在100毫秒内返回结果,否则终止,并抛出超时错误。这里铁定超时
co.timeLimit(1*100,co(function*(){
      variable+=10;
	  yield I_need_more_time();//执行准备好的耗时操作
	  variable+=10000;
	  return variable;
}))((err,result)=>{
   if(err){
      console.log(err.message);//打出 "timeout"
   }
})
//设一个更长的等待,确保上面的耗时操作都能执行完
setTimeout(function(){
    console.log(variable);//打印一下variable这个变量的值。
	// 值为 "111" ,说明加1000和加10000的操作都没有执行,因为被终止执行了。
},400);

终止协程的方法是zco模块内部使用的,如果开发者因为其他原因想要终止协程,也可以使用,给个例子:

const co=require("zco");

var zco_future=co(function*(next){
   //............
});
zco_future();//执行协程
zco_future.__zco_suspend__();//终止协程

只要持有zco的future就可以在任意时刻终止, co(), co.all(),co.timeLimit().co.wrapPromise() 都会返回一个zco的future。但是co.wrapPromise返回的future的终止方法并没有任何用,象征性的调一下,原因在于无法干预Promise内部的逻辑(有可能可以hack进去,还没研究过)。所以不推荐使用Promise。

结束语

上面列出的俩个特性是zco不同于tj 的co的主要区别。 写zco最初的目的是想抛弃Promise,因为在项目中Promise增加了额外的代码量,并且非常不喜欢Promise处理异常的方式,然而现存的coroutine模块又依赖于Promise,只好自己搞一个了。

在大家的建议和项目的需求中慢慢完善了这个模块,除了上述的示例,更多的例子可以在项目首页看到,地址: https://github.com/yyrdl/zco

欢迎提意见和建议 :)


Viewing all articles
Browse latest Browse all 14821

Trending Articles