Generator

作者: 陶六六 | 来源:发表于2018-08-28 00:07 被阅读0次

    Generator

    1. generator函数执行后不执行函数体,返回遍历器对象,调用遍历器对象next()执行函数体,直到碰到yield表达式返回
    2. Generator执行函数
      • next(arg),触发generator函数的执行,可以传参作为yield表达式的值(不传值默认undefined)
      • Generator.prototype.throw(err),向generator函数里抛出一个错误,内部捕获继续执行,如果内部没有捕获,会冒泡到函数外部,直至全局,throw(err)在内部捕获后会自动触发一次next(),throw(err)类似next(throw(error))
      • Generator.prototype.return(arg),向generator函数内部抛出一个返回,终止函数执行,return(arg)类似next(return(arg))
    3. yield* 展开一个可遍历对象
    4. 异步操作
      • 回调函数,多层嵌套回调函数可能导致回调地狱
      • Promise,链式回调函数
      • Generator
    5. 协程 多个程序并发执行,通过暂停/恢复机制转移执行权
    6. 自动执行generator函数
      • trunk函数,将多参数函数转化为只接受回调函数作为参数的单参数函数
      • Promise

    tips

    1. generator函数不是构造函数不能使用new操作符,可以通过外部包装普通函数的方式变成一个构造函数
    2. generator函数执行后始终返回遍历器对象,内部this失效,可以通过将generator函数调用者通过apply方法�切换成原型对象,从而让generator内部this指向原型对象,使内部this操作生效
    3. node约定回调函数的第一个参数必须是错误对象,因为异步操作执行分为两段,在第一段执行完以后,任务躲在的上下文环境已经结束,在这以后抛出的错误,原来的上下文环境无法捕获,所以只能作为参数传入第二段,在第二段处理
    4. Generator+Promise 任务队列
    function* Gen() {
        while (1) {
            let valueObj = {};
            let result = yield valueObj;
            valueObj.output = '============No Tasks============';
            while (this.index < this.tasks.length) {
                let task = this.tasks[this.index++];
                valueObj.output = task(...result);
                result = yield valueObj;
            }
            valueObj.done = 1;
            yield valueObj;
        }
    }
    const NEXT = Symbol('next');
    const SERIALIZE = Symbol('serialize');
    const STARTON = Symbol('start-on');
    Object.assign(Gen.prototype, {
        [NEXT]: function (...input) {
            var that = this;
            if (!that.value.done) {
                that.next(input);
                Promise.resolve(that.value.output).then(function (output) {
                    that.value.done || console.log(output);
                    output instanceof Array ? that[NEXT](...output) : that[NEXT](output);
                }).catch(function (err) {
                    setTimeout(() => {
                        throw err;
                    }, 0);
                });
            } else {
                // console.log('============Task Done============\noutput:');
                that[STARTON] = false;
                typeof that.resolve === 'function' && that.resolve(that.value.output);
            }
        },
        [SERIALIZE]: function (tasks, target) {
            for (let task of tasks) {
                try {
                    if (typeof task === 'function') {
                        target.push(task);
                    } else {
                        task && task[Symbol.iterator] && that[SERIALIZE](task, target);
                    }
                } catch (e) {}
            }
        }
    });
    const PROTO = Gen.prototype;
    
    function TaskMachine(...tasks) {
        Gen.prototype = Object.create(PROTO);
        var f = Gen.call(Gen.prototype);
        Object.assign(f, {
            next(input) {
                var that = this;
                var output = that.__proto__.next.call(that, input);
                Object.assign(that, output);
                return that;
            },
            init(...tasks) {
                var that = this;
                that.__proto__.tasks = [];
                that.__proto__.index = 0;
                that[SERIALIZE](tasks, that.__proto__.tasks);
                return that;
            },
            add(...tasks) {
                this.value && this.value.done ? this.init(...tasks) : this[SERIALIZE](tasks, this.__proto__.tasks);
                return this;
            },
            start(...input) {
                // console.log('============Task Start============')
                var that = this;
                if (!that[STARTON]) {
                    that[STARTON] = true;
                    that.next();
                    that.value = that.value || {}
                    return new Promise(function (resolve) {
                        that.resolve = resolve;
                        that[NEXT](...input);
                    });
                } else {
                    return Promise.resolve('============On Going============');
                }
            }
        });
        f.init(...tasks);
        return f;
    }
    module.exports = TaskMachine
    

    相关文章

      网友评论

          本文标题:Generator

          本文链接:https://www.haomeiwen.com/subject/eudxwftx.html