理解 Co 库的源码

2016-12-13 11:58:17 +08:00
 huangyanxong

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

简单版本的 Co 库

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

// @flow
/**
 * Created by Freax on 16-12-12.
 * @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
/**
 * Created by Freax on 16-12-12.
 * @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

1957 次点击
所在节点    Node.js
2 条回复
iugo
2016-12-13 14:29:34 +08:00
我对此有点模糊.

不过想要全面理解 generators 还是要先理解 iterators.
huangyanxong
2016-12-13 19:07:30 +08:00
@iugo generator 调用 generators 后返回的是可遍历迭代器,这个迭代器有个 next 的方法,方法返回的是一个对象{done:false,value:1},对象的 done 属性的 true 代表已经遍历完毕

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/327271

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX