Nodejs 理解 Co 库的源码

发布于 1周前 作者 ionicwang 来自 nodejs/Nestjs

Nodejs 理解 Co 库的源码

Co 流程流程控制器源码与理解,index.js 包含理解和注释

简单版本的 Co 库

这个版本是重点是理解 generator 工作原理

// [@flow](/user/flow)
/**
 * Created by Freax on 16-12-12.
 * [@Blog](/user/Blog) http://www.myfreax.com/
 */
function co(generator) {
    let gen = generator();
    next(gen.next()); //递归遍历 generator.next
    function next(result) {
        if (result.done)return null;//如果 generator 执行完毕,直接解决退出遍历
        let res = gen.next(result.value);
        next(res);
    }
}

co(function *gen() { let a = yield 1; console.info(a, ‘a’); let b = yield 2; console.info(b, ‘b’); let c = yield 3; console.info(c, ‘c’); });

generator+promise Co 库的简版

理解 generator+promise 如何工作

// [@flow](/user/flow)
/**
 * Created by Freax on 16-12-12.
 * [@Blog](/user/Blog) http://www.myfreax.com/
 */

function isPromise(obj) { return typeof obj === ‘object’ && ‘function’ == typeof obj.then; }

function co(generator) { return new Promise((resolve,reject)=>{ let gen = generator(); next(gen.next()); function next(result) { if (result.done)return resolve(result.value);//如果 generator 执行完毕,直接解决退出遍历 //判断是否是 Promise ,如果是 promise 则执行 promise 再进入 next 递归遍历 generator.next if (isPromise(result.value))return result.value.then(res => { let result; try { result = gen.next(res); //抛出 generator 的错误 }catch (e){ return reject(e);// 捕获后由交给 promise 处理返回外部处理 } next(result) }, err => { let result; try { result = gen.throw(err); //yield 返回 promise 进入 reject 后的错误,抛出 generator 的错误 }catch (e){ return reject(e); // 捕获后由交给 promise 处理返回外部处理 } next(result) }); let res = gen.next(result.value); next(res); } });

}

co(function *gen() { let a = yield Promise.resolve(1); console.info(a, ‘a’); let b = yield 2; console.info(b, ‘b’); let c = yield 3; console.info(c, ‘c’);

}).catch((err)=>{ console.info(err); });

Github 欢迎提交 PR or ISSUE


3 回复

我对此有点模糊.

不过想要全面理解 generators 还是要先理解 iterators.


generator 调用 generators 后返回的是可遍历迭代器,这个迭代器有个 next 的方法,方法返回的是一个对象{done:false,value:1},对象的 done 属性的 true 代表已经遍历完毕

当然,我可以帮你概括性地解释Node.js中co库的源码及其工作机制。co库是一个用于生成器函数(generator functions)的协程库,它使得异步代码看起来像同步代码。

首先,co库的核心在于对生成器函数的处理。一个生成器函数可以通过function*语法定义,并使用yield关键字来暂停和恢复执行。

以下是co库的基本工作原理:

  1. co函数接受一个生成器函数作为参数,并立即执行它。
  2. 使用yield关键字调用的每个Promise都会被co处理,co会等待Promise解决(resolve)或拒绝(reject),然后恢复生成器的执行。

下面是一个简单的co函数实现示例:

function co(gen) {
  return new Promise((resolve, reject) => {
    const it = gen();

    function next(value) {
      const { done, value: nextValue } = it.next(value);
      if (done) {
        resolve(nextValue);
      } else {
        Promise.resolve(nextValue).then(next, reject);
      }
    }

    next();
  });
}

// 使用示例
co(function* () {
  const result = yield Promise.resolve(42);
  console.log(result); // 输出 42
}).catch(console.error);

在这个示例中,co函数创建一个新的Promise,并通过it.next()方法迭代生成器。每次迭代时,如果生成器函数返回一个新的Promise,co会等待该Promise完成,然后将结果作为参数传递给生成器的下一个next()调用。

通过这种方式,co库使得处理异步代码变得更加直观和简洁。

回到顶部