generator在定义上跟普通函数差不多,不过在function的后面加上一个*(星号),而且另外不同的是,普通函数只能有一个return 返回值,但是generator中可以定义多个yield,相当于多个返回值,然后需要调用next()方法取到每个return的值了。而generator定义的函数的实例,其实是一个Iterator对象,通过它来遍历每一个状态。
{
const say = function*(){
yield 'a'
yield 'b'
yield 'c'
}
const fn = say()
console.log(fn.next())
}
然后控制台输出
多次调用.next()后
?
{
const say = function*(){
yield 'a'
yield 'b'
yield 'c'
}
const fn = say()
console.log(fn.next())
console.log(fn.next())
console.log(fn.next())
console.log(fn.next())
}
?
控制台输出
我们可以利用这个特性,很方便的遍历对象属性的每个值。像下面这样。?
{
let obj = {
a:1,
b:2,
c:3
}
obj[Sybol.iterator] = function*(){
for(const key of Object.keys(obj)){
yield obj[key]
}
}
for(const value of obj){
console.log(value)
}
}
?还有两种概念
1.状态机
{
// 状态机:任何时候都只有一定数量状态
const state = function*(){
while(1){
yield 'success'
yield 'fail'
yield 'pending'
}
}
const stateData = state();
console.log(stateData.next());
console.log(stateData.next());
console.log(stateData.next());
console.log(stateData.next());
}
?
?2.长轮询,这里模拟异步操作
{
// 长轮询
function fn1(){
return new Promise(resolve=>{
setTimeout(() => {
console.log('查询中');
resolve({code:1})
}, 1000);
})
}
const getStatus = function*(){
yield fn1()
}
function autoGetStatus(){
// 获取一个Generator实力,也就是一个迭代器
const gen = getStatus()
// 通过next犯法嗲用了上面getStatus函数中yield fn1()函数拿到一个Promise对象
const status = gen.next();
status.value.then(res=>{
if(res.code===0){
console.log('用户付款成功');
}else{
console.log('暂未付款');
setTimeout(() => {
autoGetStatus();
}, 500);
}
})
}
autoGetStatus()
}
控制台不断打印?
?
?这个代码块的执行会一直向用户查询是否付款,若没付款则会不断查询并显示暂未付款。
|