Generator生成器基本语法
/*--创建一个生成器--*/
function * generator(){
console.log('ok');
}
//generator()并不会把函数执行 而是返回个generator实例 也可以说 生成器执行返回迭代器
let g = generator();
console.log(g);
console.log(g instanceof generator) //=>true
/*
g的原型链上拥有
+ next
+ return
+ throw
+ Symbol.toStringTag : 'Generator'
*/
next使用
/*
g.next()返回一个对象里面包含value,done
yield 后面的 作为value中的值
*/
function * generator(){
console.log('A');
yield 1;
console.log('B');
yield 2;
console.log('C');
yield 3;
console.log('D');
return 4
}
let g = generator();
console.log(g.next()); //=>{value:1,done:false}
console.log(g.next()); //=>{value:2,done:false}
console.log(g.next()); //=>{value:3,done:false}
console.log(g.next()); //=>{value:4,done:true}
console.log(g.next()); //=>{value:undefined,done:true}
/*---*next传参---*/
function * generator(){
console.log('A');
//如果第二个next什么都没传a就是undefined
let a= yield 1;
console.log('B',a); //=>B 要
let b= yield 2;
console.log('C',b); //=>C 学
let c= yield 3;
console.log('D',c); //=>C 习
return 4
}
let g = generator();
console.log(g.next('我'));
console.log(g.next('要'));
console.log(g.next('学'));
console.log(g.next('习'));
/*
@1 走到yield 那一行就会停止
@2 next('参数是给上一个yield赋值不传就是undefined')
*/
生成器函数嵌套生成器函数
function * generator1 (){
yield 1;
yield 2;
yield generator2();
}
function * generator2 (){
yield 4;
yield 5;
yield 6;
}
let g = generator1();
console.log(g.next()); //=>{value:1,done:false}
console.log(g.next()); //=>{value:2,done:false}
console.log(g.next()); //=>{value:generator2,done:true}
/*------------*/
function * generator1 (){
yield 1;
yield 2;
// '*' + 'generator2()返回的迭代器'
yield * generator2();
}
function * generator2 (){
yield 4;
yield 5;
yield 6;
}
let g = generator1();
console.log(g.next()); //=>{value:1,done:false}
console.log(g.next()); //=>{value:2,done:false}
console.log(g.next()); //=>{value:4,done:false}
console.log(g.next()); //=>{value:5,done:false}
console.log(g.next()); //=>{value:6,done:false}
console.log(g.next()); //=>{value:undefined,done:true}
发送串行请求
方法一 :基于Promise中的then链实现即可
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(wait);
},wait)
})
}
query(1000).then((res) => {
console.log("第一次执行",res); //一秒后输出 1000
//如果不返回一个状态不确定的promise 下面那个then就会立即执行
return query(2000);
}).then((res) => {
console.log("第二次执行",res); //再过两秒后输出 2000
})
方法二 :generator生成实例手动一次次调用next
/*
思路:
@1 运用next一步一步执行
第一次 g.next() => let result = yield query(1000); 执行后返回一个promise在value中状态为pedding,等一秒后定时器到了状态变为fulfilled开始执行then
第二次 g.next(res) => @1 console.log(result); @2result = yield query(2000); 第二次是在第一次状态变为fulfilled开始执行then的时候触发的 输出第一次的结果 g.next(res)中需要传res给上一次的yield
.....
最后一次 g.next(res) => console.log(result);输出 返回 {value:undefined,done:true}
*/
const query = wait => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(wait);
}, wait)
})
}
function* generator() {
let result = yield query(1000);
console.log(result);
result = yield query(2000);
console.log(result);
result = yield query(3000);
console.log(result);
}
let g = generator();
//g.next().value 这是一个promise 等他定时器到了一秒我们就进入then
g.next().value.then((res) => {
g.next(res).value.then((res) => {
g.next(res).value.then((res) => {
g.next(res);
})
})
})
上面产生的回调地狱十分恶心 我们可以写一个函数自动帮我们执行
generator + promise
// 判断一个参数是不是promise
const isPromise = function isPromise(obj) {
if (obj !== 'null' && /(function|object)/i.test(typeof (obj))) {
if (typeof (obj.then) === 'function') {
return true
}
}
return false;
}
/*
执行query 传一个参数 返回值是一个promise 里面有个定时器 定时器时间到了把promise的状态改变
*/
const query = wait => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(wait);
}, wait)
})
}
function* generator() {
let result = yield query(1000);
console.log(result);
result = yield 1;
//result = yield Promise.reject('NONO');
console.log(result);
result = yield query(3000);
console.log(result);
}
//创建一个AsyncFunction函数 形参:generator生成器函数
const AsyncFunction = function AsyncFunction(generator, ...args) {
//返回一个promise对象
return new Promise((resolve, reject) => {
//执行生成器函数generator 返回一个迭代器 Iterator 缩写itor
let itor = generator();
//定义一个next方法 用来之后的递归 接受一个参数x
const next = x => {
//@1 第一次进来x是undefined itor.next(x) => let result = yield query(1000) 返回{value:promise,done:false}
let { value, done } = itor.next(x);
//如果itor.next(x)执行返回的done为true就说明generator执行完了
if (done) {
resolve('OK'); //直接返回
return; //递归结束
}
//判断一下value是不是promise 如果不是就转换成promise 确保value是一个promise
if(!isPromise(value)) value = Promise.resolve(value);
value.then((res) => {
//第一次定时器结束 promise状态确定 就递归调用
/*
分析一下res
+ 第一次res是1000,是resolve(wait);中wait传过来的
+ next(res);不写就不能给x传参itor.next(x)=> console.log(result);
result = yield query(2000); 中的result就是undefined 应为没有给上一次yield传值
*/
next(res);
}, (err) => {
/*
为什么只能拿到 yield query(2000)中的错误
value拿到的promise是yield返回的
*/
reject(err);
})
}
//第一次执行不传参数
next();
})
}
AsyncFunction(generator).then((res) => {
console.log(res);
}).catch(err => {
console.log(err);
});
处理异步的终极方案
async await
原理就是 generator + promise
const query = wait => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(wait);
}, wait)
})
}
async function generator() {
let result = await query(1000);
console.log(result);
result = await query(2000);
console.log(result);
result = await query(3000);
console.log(result);
}
generator()