利用generator模拟协程完美解决异步回调问题

一直不喜欢es6/7的promise、await、async之流对异步回调的解决方案,个人觉得类似lua里面协程的语法处理异步回调更顺眼,es6的generator虽然不完美,但是可以简单模拟一下协程。经过简单封装,完美解决异步回调的问题,要多个异步并行就并行,要串行就串行。
直接上代码:

/**
 * 执行生成器
 * @param {Generator} generator 生成器函数(this指针里面有next函数和genInst原始生成器实例,参数由args传入)
 * @param {Array} args 传递给生成器的参数数组(可以为空)
 * @param {Function} end 生成器执行完之后的回调函数(可以为空),参数为生成器的返回值
 */
var runGenerator = function (generator, args, end){
    var co = {};
    var genInst;
    co.next = function (){
        var rsl = genInst.next.apply(genInst, arguments);
        if(rsl.done){
            end && end(rsl.value);
        }
    };
    genInst = generator.apply(co, args || []);
    co.genInst = genInst;
    co.next();
};

//测试异步函数
var asyncTest = function (person, cb){
    setTimeout(function (){
        cb(undefined, "hi " + person);
    }, 1000);
};

runGenerator(function* (ctx, next){
    var _this = this;
    console.log("start");
    var recvArg = function (){
        //生成器的_this.next函数参数会在下一个yield点传出
        //js不支持多返回值,把参数当成数组,利用解构赋值来模拟
        _this.next(arguments);
    };
    asyncTest("John", recvArg);
    var [err, greeting] = yield;
    if(err){
        console.error(err);
    } else {
        console.log(greeting);
    }
    console.log("end");
});

 补充:

随着对promise了解的深入,对此问题有新的认识。promise解决的不是回调的缩进问题,解决的是回调的信任问题,generator才是解决回调缩进问题的方法。所以两者并不冲突,可以配合使用。

原文地址:https://www.cnblogs.com/omega8/p/9605471.html