在讲生成器之前需要知道迭代器的用法,所以我们先来讲一下迭代器
一、迭代器
概念:迭代器是一个接口,能快捷地访问数据,通过Symbol.iterator来创建迭代器,通过迭代器的next()来获取迭代之后的结果。
- <script>
- const items = ['one', 'two', 'three'];
- const ite = items[Symbol.iterator]();
- // value表示遍历的值,done表示遍历继续,如果为true表示遍历完成
- console.log(ite.next()); //{value: 'one', done: false}
- console.log(ite.next()); //{value: 'two', done: false}
- console.log(ite.next()); //{value: 'three', done: false}
- console.log(ite.next()); //{value: undefined, done: true}
- script>
items[Symbol.iterator]是一个函数,所以返回迭代器的时候需要在后面加()进行掉用来返回迭代器
二、生成器
作用:generator函数可以通过yield关键字将函数挂起,为改变执行流提供了可能,同时为了做异步编程提供了方案。
它和普通函数的差别在于:
1.function后面函数名前面要加*
2.只能在函数内部使用yield表达式,让函数挂起
我们来看下面这段代码:
- <script>
- function* func() {
- console.log('one');
- yield 2;
- console.log('two');
- yield 3;
- console.log('three');
- }
- // 返回一个迭代器对象,阔以调用next
- let fn = func();
- console.log(fn.next());
- console.log(fn.next());
- console.log(fn.next());
- script>
输出结果是:
总结:generator函数是分段执行的,yield语句是暂停执行,而next()是恢复执行。
我们再来看一段代码:
- <script>
- function* add() {
- console.log('start');
- // x不是yield '2'的返回值,它是next()调用恢复当前yield()执行传入的实参
- let x = yield '2';
- console.log('one:' + x);
- let y = yield '3';
- console.log('two:' + y);
- return x + y;
- }
- let fn = add();
- console.log(fn.next());
- console.log(fn.next(20));
- console.log(fn.next(30));
- script>
输出结果:
使用场景:为不具备Iterator接口的对象提供了遍历操作,下面这个代码也要认真看
- <script>
- function* func(obj) {
- const propKeys = Object.keys(obj);
- for (const keys of propKeys) {
- yield [keys, obj[keys]];
- }
- }
- const obj = {
- name: 'sy',
- age: 18
- }
- for (let [key, value] of func(obj)) {
- console.log(`${key},${value}`);
- }
- script>
输出结果:
三、生成器的应用
我们先来看什么是回调地狱:

简单来说就是去使用ajax发送请求的时候在里面收到数据后又发送请求,然后重复上面的操作。上面这样对异步编码非常不友好,这个时候就阔以使用生成器将异步代码同步化。
再来看一个例子(重要):
- <script>
- // 加载loading...页面
- // 数据加载完成...(异步操作)
- // loading关闭掉
- function* load() {
- loadui();
- yield showdata();
- hideui();
- }
- let ite = load();
- ite.next();
-
- function loadui() {
- console.log('加载loading...页面');
- }
-
- function showdata() {
- setTimeout(function() {
- console.log('数据加载完成');
- ite.next();
- }, 1000);
- }
-
- function hideui() {
- console.log('隐藏loading...页面');
- }
- script>