在讲生成器之前需要知道迭代器的用法,所以我们先来讲一下迭代器
一、迭代器
概念:迭代器是一个接口,能快捷地访问数据,通过Symbol.iterator来创建迭代器,通过迭代器的next()来获取迭代之后的结果。
- 我们直接来看下面这段代码:
<body>
<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>
</body>
items[Symbol.iterator]是一个函数,所以返回迭代器的时候需要在后面加()进行掉用来返回迭代器
二、生成器
作用:generator函数可以通过yield关键字将函数挂起,为改变执行流提供了可能,同时为了做异步编程提供了方案。
它和普通函数的差别在于:
1.function后面函数名前面要加*
2.只能在函数内部使用yield表达式,让函数挂起
我们来看下面这段代码:
<body>
<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>
</body>
输出结果是:
总结:generator函数是分段执行的,yield语句是暂停执行,而next()是恢复执行。
我们再来看一段代码:
<body>
<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>
</body>
输出结果:
使用场景:为不具备Iterator接口的对象提供了遍历操作,下面这个代码也要认真看
<body>
<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>
</body>
输出结果:
三、生成器的应用
我们先来看什么是回调地狱:
简单来说就是去使用ajax发送请求的时候在里面收到数据后又发送请求,然后重复上面的操作。上面这样对异步编码非常不友好,这个时候就阔以使用生成器将异步代码同步化。
再来看一个例子(重要):
<body>
<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>
</body>