Sign in
Log inSign up
How does co work

How does co work

Yanni Nightingale's photo
Yanni Nightingale
·Oct 13, 2016

co is a library that can wrap a generator function to a promise object, e.g.

function* add (x, y) {
    var m = yield Promise.resolve(x);
    var n = yield Promise.resolve(y);
    return m + n;
}

co(add, 1, 2).then(sum => {
    console.log(sum); // 3
});

But how does it work? What's the magic? Actually, it is internally walking the generator.

Let's define a simple co function takes a generator function as an argument, a promise returned:

function co (gfn) {
    return new Promise((resolve, reject) => {
    });
}

Create a generator object:

var g = gfn();

And next:

var ret = g.next();

if (ret.done) {
    resolve(ret.value);
}

As you can see above, fulfill the promise if done. Or the value of ret should also be a promise object behind the yield expression. If this promise is fulfilled, we should call next() again. So, we create a function:

function done(m)  {
    var ret = g.next(m);
    if (ret.done)  {
        resolve(ret.value);
    } else {
        ret.value.then(done, reject);
    }
}

Finally we call done(). All codes:

function co () {
    var gfn = arguments[0];
    var args = Array.prototype.slice.call(arguments, 1);

    return new Promise((resolve, reject) => {
        var g = gfn.apply(null, args);

        function done(m)  {
            var ret = g.next(m);
            if (ret.done)  {
                resolve(ret.value);
            } else {
                ret.value.then(done, reject);
            }
        }

        done();
    });
}

Here we did not consider exceptions.

Now we use our co function:

co(all, 1, 2).then(sum => {
    console.log(sum);// 3
})

This is core of co. It's not that complicated, just understand how to use ES2015's generator.