Generator
- generator函数执行后不执行函数体,返回遍历器对象,调用遍历器对象next()执行函数体,直到碰到yield表达式返回
- 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))
- yield* 展开一个可遍历对象
- 异步操作
- 回调函数,多层嵌套回调函数可能导致回调地狱
- Promise,链式回调函数
- Generator
- 协程 多个程序并发执行,通过暂停/恢复机制转移执行权
- 自动执行generator函数
- trunk函数,将多参数函数转化为只接受回调函数作为参数的单参数函数
- Promise
tips
- generator函数不是构造函数不能使用new操作符,可以通过外部包装普通函数的方式变成一个构造函数
- generator函数执行后始终返回遍历器对象,内部this失效,可以通过将generator函数调用者通过apply方法�切换成原型对象,从而让generator内部this指向原型对象,使内部this操作生效
- node约定回调函数的第一个参数必须是错误对象,因为异步操作执行分为两段,在第一段执行完以后,任务躲在的上下文环境已经结束,在这以后抛出的错误,原来的上下文环境无法捕获,所以只能作为参数传入第二段,在第二段处理
- 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
网友评论