JS生成器generator,yield关键字的阻塞原理

如何使用generator

generator其实本身就是一个迭代器iterator

什么是迭代器?

参考https://blog.csdn.net/qq_18433441/article/details/78223502

上面文章中讲解了Java的迭代器:
集合类Collection实现了接口Iterator
所以任何集合类都有一个iterator实例

Iterator iterList= list.iterator();//List接口实现了`Iterable接口

通过

while (iterList.hasNext()){
String str = iterList.next();
}

来遍历迭代器获取元素


那么回到Javascript
ES6才出现generator这么一个对象,
声明generator需要在function后面加上星号*,在函数体中使用”yield”关键字就能将当前函数变成一个地地道道generator函数。

老规矩,先贴代码

function* fn(){
let a=1;
	yield a;
a++;
	yield a;
a++;
return a
}

let t = fn();
console.log(t);	//fn {<suspended>}
let res = t.next(); 
console.log(res) //{value: 1, done: false}
res = t.next(); 
console.log(res) //{value: 2, done: false}
res = t.next(); 
console.log(res) //{value: 3, done: true}

使用步骤如下:
1.定义一个函数(记得加*)并在函数体内部使用yield关键字
function* fn(){
let a=1;
yield a;
a++;
yield a;
}

2.在外面将改函数实例化,并赋值给一个变量。
let t = fn();

3.然后t就是一个迭代器了,通过next()方法获取包含变量值的对象(学术名叫做IteratorResult )。
每次使用t.next()都会获取一个IteratorResult对象,这个是yield的返回值(上面例子中的a),yield等同于return!记住这句话。只不过是带阻塞功能且会把返回值封装成一个IteratorResult对象(下面说的res)。

4.如果我们保存返回值
var res = t.next()
那么res就是该对象,包含两个属性——{ value: xxx , done: true/false}
在这里插入图片描述
value是yield关键字后面的对象值(上面说的a);done是用来判断是否通关完所有的yield了(也就是运行途中再也没有遇到yield关键字)


但是,通过所有yield之后再次调用t.next()会遇到如下两种情况:
一:遇到return,那么t.next()的值就等于{ value: (return的值),done:true }
二:没有return了,那么t.next()的值就等于{ value: undefined , done:true}


yield的阻塞原理

上面留下了一个坑,就是——yield是怎么阻塞的?实在yield这行代码之前阻塞住还是之后阻塞住?
解答:这个问题不是所有人都会跟你讲的,我也是自己研究的,首先抛出结论——yield之后

继续只用这段代码

function* fn(){
let a=1;
	yield a;
a++;
	yield a;
a++;
return a
}

如果是在yield之前堵塞住,那么调用fn()的时候,a就应该被赋值为1了,但是实际上是undefined。
在这里插入图片描述

当res = fn()且res.next()通过第一个yield之后。
在这里插入图片描述

a才被赋值为1,但是如果是每通过yield就会把下一次yield之前的代码全部执行完毕的话,那么a++也会被执行,此时a=2而不是等于1了。

所以得出结论:
第一次运行fn(),一句代码都不会执行;当执行next(),则会一路畅行直到碰到一个yield,然后会在执行完yield这行代码之后阻塞住。
通过最后一个yield之后代码不会直接执行完毕,否则上面说的return就直接和最后一次yield返回值冲突了(先返回yield的值,然后顺序执行到return又把之前的值覆盖),这是矛盾的,所以通过最后一个yield之后代码仍然阻塞。
然后最后再执行一次next(),代码就会继续往下执行直到碰到一个return,代码执行完毕返回{value:3,done:true}(或者没有遇到return执行完毕返回{value:undefined,done:true})


如果你想更详细地了解yield,我推荐这位博主的文章
深入理解js的yeild
欢迎指错,转载请加上原文链接:
https://blog.csdn.net/weixin_51116314/article/details/114672960

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值