<<< co.ts >>>
//
// Module to help escape from callback-hell by using semi-coroutine(generator).
//

function co<E, T>(generator: GeneratorFunction,
        callback: (err: E, result: T) => void) {
    function *wrapper(resolve: any, reject: any) {
        let wrapperGenerator: Generator = yield;
        try {
            let result = yield* (<any>generator)(wrapperGenerator);
            resolve(result);
        } catch (e) {
            reject(e);
        }
    }

    new Promise<T>((resolve, reject) => {
        let w = wrapper(resolve, reject);
        w.next(); // run function
        w.next(w);
    }).then(r => {
        callback(<any>undefined, r);
    }, e => {
        callback(e, <any>undefined);
    });
}

export = co;


<< main.ts >>

import co = require('./co');


describe('co', function() {
    it('co success', done => {
        co<string, Array<Number>>(<any> function* (gen: Generator) {
            let path = new Array<Number>();
            path.push(10);
            setTimeout(() => {
                path.push(20);
                gen.next();
            }, 200);
            yield;
            path.push(30);
            return path;
        }, (err, result) => {
            assert.ok(undefined === err
                && 3 === result.length
                && result[0] === 10
                && result[1] === 20
                && result[2] === 30);
            done();
        });
    });

    it('co fails: throw in generator', done => {
        co<string, string>(<any> function* (gen: Generator) {
            setTimeout(() => {
            }, 200);
            if (gen) {
                throw 'error';
            }
            return 'hello';
        }, (err, result) => {
            assert.ok(undefined === result
                && 'error' === err);
            done();
        });
    });

    /*
     * This test gives unexpected error at mocha. But works well at normal environment.
     *
     *
     * (node:41022) UnhandledPromiseRejectionWarning: Unhandled promise rejection...
     * (node:41022) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated....
     * node_modules/mocha/lib/runner.js:690
     * err.uncaught = true;
     *            ^

     * TypeError: Cannot create property 'uncaught' on string 'error'
     *     at Runner.uncaught ...
     *     ...
     *

    it('co fails: Generator.throw', done => {
        let path = new Array<Number>();
        co<string, string>(<any> function* (gen: Generator) {
            setTimeout(() => {
                gen.throw!('error');
                path.push(10);
                return;
            }, 200);
            return 'done';
        }, (err, result) => {
            assert.ok(undefined === result
                && 'error' === err
                && 1 === path.length);
            done();
        });
    });
    */
});


+ Recent posts