精华 co最简版实现,学习generator & co
发布于 4 年前 作者 ltebean 24869 次浏览 最后一次编辑是 2 年前 来自 分享

看了co的源码 比较难懂 了解了其原理后实现了一个最简版本https://github.com/yucong/simple-co 希望对想学习的tx有帮助~ yeild后面只支持thunk,co本身也是一个thunk 核心代码:

function co(generator) {
  return function(fn) {
	var gen = generator();
	function next(err, result) {
		if(err){
			return fn(err);
		}
		var step = gen.next(result);
		if (!step.done) {
			step.value(next);
		} else {
			fn(null, step.value);
		}
	}
	next();
   }
}

用法:

var co = require('./co');
// wrap the function to thunk
function readFile(filename) {
    return function(callback) {
	    require('fs').readFile(filename, 'utf8', callback);
    };
}

co(function * () {
    var file1 = yield readFile('./file/a.txt');
    var file2 = yield readFile('./file/b.txt');

    console.log(file1);
    console.log(file2);
    return 'done';
})(function(err, result) {
    console.log(result)
});

会打印出: content in a.txt content in b.txt done

13 回复

好东西, 这样许多人学习起来会省很多力气

不错,有货。

赞,可以继续写续篇,说说try catch是如何做到的。

return function(fn) {} ,看的不是很懂,返回一个函数有什么用? 好心的lz可以解释下吗?

返回一个functoin是为了把一个普通的函数变成thunk thunk类似与promise, 可以把一个函数延后执行,每个thunk函数只有一个参数 这段代码就是将一个普通的nodejs函数转换为thunk:

function readFile(filename) {
    return function(callback) {
        require('fs').readFile(filename, 'utf8', callback);
   };
}

当你调用readFile(‘a.txt’)的时候并不会去读取文件,它会返回一个function,然后通过这个function去执行:

 readFile('a.txt')(function(err,result){
 });

把普通的函数转为thunk是为了配合co的实现(能够被yield),TJ大神写过一个库可以方便地将普通的nodejs函数转换成thunk(https://github.com/visionmedia/node-thunkify) 这里的co函数返回一个function(fn)是为了把co函数本身也变成一个thunk,这样就可以被yield了

@ltebean 我把co源码里 return function (done) {} 这2行注释了 co也能正常运行,是不是说明return function(){} 一般情况下没什么用? 还有返回的function里面的内容怎么会自动执行的?匿名函数不是应该这样才会执行吗? (function(){ })();

谢谢楼主,我是看着这个代码搞明白co和thunkify的基本原理的。 如果还有人没明白,http://blog.shiqichan.com/using-es6-generators-in-nodejs/ 我写了个日志,又做了下拆解,换了个ping获取mac地址的例子。 希望能帮助到需要的人。

要看懂Co, 建议先将generator的基本特性了解清楚 特别几个东东: gen.next , 特别是带参数的gen.next(args), 还有就是返回值ret.value, ret.done等 gen.throw, 了解try catch如何做到的? yield, yield和gen.next的关系? yield* 和yield的关系?有什么好处?

理解了下这个代码,写了个文章。跟我一样的初学者可以参考 http://www.html-js.com/article/Nodejs-study-notes-to-understand-co-execution-logic

博主 还能回答问题不?为什么我运行项目 Debugger listening on port 18507 f:\nodejs\node-study\generator\Test4.js:27 })(function(err,result){ ^ TypeError: object is not a function

太好了, 太有参考价值了.

@LastKing 可能是因為你用的Node版本是4.0以上, 你去co的原始碼看,我沒有研究先改成這樣寫是OK的, https://github.com/tj/co 把下面這段

(function(err, result) { console.log(result) });

改寫成下面這樣應該就OK了!

.then(function (result){ console.log(result); }, function(err){ console.log(err); });

回到顶部