看了co的源码 比较难懂 了解了其原理后实现了一个最简版本https://github.com/yucong/simple-co 希望对想学习的tx有帮助~ yeild后面只支持thunk,co本身也是一个thunk 核心代码:
JavaScript代码
- 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();
- }
- }
用法:
JavaScript代码
- 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
下面做个简单对比:
传统方式,sayhello
是一个异步函数,执行helloworld
会先输出"world"
再输出"hello"
。
JavaScript代码
- function sayhello() {
- return Promise.resolve('hello').then(function(hello) {
- console.log(hello);
- });
- }
- function helloworld() {
- sayhello();
- console.log('world');
- }
- helloworld();
输出
JavaScript代码
- > "world"
- > "hello"
co 的方式,会先输出"hello"
再输出"world"
。
JavaScript代码
- function co(gen) {
- var it = gen();
- var ret = it.next();
- ret.value.then(function(res) {
- it.next(res);
- });
- }
- function sayhello() {
- return Promise.resolve('hello').then(function(hello) {
- console.log(hello);
- });
- }
- co(function *helloworld() {
- yield sayhello();
- console.log('world');
- });
输出
JavaScript代码
- > "hello"
- > "world"
消除回调金字塔
假设sayhello
/sayworld
/saybye
是三个异步函数,用真正的 co 模块就可以这么写:
JavaScript代码
- var co = require('co');
- co(function *() {
- yield sayhello();
- yield sayworld();
- yield saybye();
- });
输出
JavaScript代码
- > "hello"
- > "world"
- > "bye"