特点一、generator是一个生产器,生成器的作用是返回一个迭代器。
function* read(){
yield 'node'; // yield 产出
yield 'javascript';
}
let a = read();
console.log(a); //Object [Generator] {}
console.log(a.next()); // {value:"node",done:false}
//调用next()方法才会往下执行。
特点二、错误异常的捕获。支持try、catch捕获异常
function* read() { //generator生成器
try {
yield 'node';
yield 'javascript';
}catch (e) {
console.log(e);
}
}
if(a.next().value === 'node'){
a.throw("异常错误了");
}
//要想触发catch捕获异常需要手动调用迭代器的throw方法抛出异常。
特点三、特殊的传参。
function* read(){
try{
let q = yield 'node';
console.log(q);
let w = yield 'javascript';
console.log(w);
}catch(e){
console.log(e);
}
}
let p = read();
p.next(); //此时不会执行打印q因为,每一次next只是走到当前的yield就会停止
p.next(); //此时q打印的为undefined,因为q获取的是next()方法执行时的参数会被作为yield的返回值。
p.next(12); //此时w打印的值为12,参数12被作为yield的返回值赋值给w所以此时的w是有值的。并且,第一个next传入的参数是没有实际意义的。因为第一个next()执行的时候,前面没有yield所以无法作为返回值返回。
如何将一个genertor函数的内容放置到另一个genertor里面?
function* a(){
yield 1;
yield 2;
}
function* b(){
yield 3;
yield 4;
}
//以下写法可以认为将a方法的内容放置在b里面去执行
function* b(){
yield * a()
yield 3;
yield 4;
}
let c = b();
console.log(c.next());
console.log(c.next());
console.log(c.next());
console.log(c.next());
console.log(c.next());
扩展实现一个co库(CO库是为了解决不停的调用next方法而写的一个库使用方法和实现如下)
function* read() {
try{
let a = yield '1';
let b = "今年"+a+"岁了";
return b;
}catch(e){
console.log(e);
}
}
//使用方法、安装一个CO库引入,将generator函数传入然后会返回一个promise。直接then即可
//这里将自己实现一个co库如下。
co(read()).then(data=>{
console.log(data);
});
//co实现
function co(it) {
return new Promise((resolve,reject)=>{ // 1
function next(data) { // 2
let { value , done} = it.next(data); // 3
if(done){ // 4
resolve(value); // 5
}else{ // 6
Promise.resolve(value).then(data=>{ // 7
next(data); // 8
},err=>it.throw("失败了")); // 9
}
}
next() //12
})
}
/*
因为co返回值可以then调用说明返回的是一个promise。所以,第一行直接返回一个promise
第二行将next封装成一个独立的方法,为的是可以在内部实现递归调用。
第三行是一个赋值结构,拿到it.next()的执行结果跟read方法是否执行完的信息。参数是拿到上一个yeild的返回值,第一次执行时没有传参为undefined,其实也没有关系,反正第一次的传参不会被方法使用。见上文特点三
第四行判断当前是否执行完毕,如果是直接在第五行让当前的promise成功即可。
第六行如果没有执行完毕。继续执行,因为此时的value可能是一个promise也可能是一个基础数据的值。所以使用第七行的promise.resolve包装,这样,假如value是一个promise那么会等待当前的promise执行完成拿到返回值。如果value不是一个promise就将它变成一个promise。
第八行将最终的value传入next中作为yeild的返回值递归执行。
第九行,执行异常的时候抛出异常信息。见特点二
第十二行,启动next的第一次执行
*/