这里写目录标题
- 一、基本概念
- 二、代码
- 三、Generator 函数的异步应用
- 三级目录
一、基本概念
- Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同,Generator 函数有多种理解角度。
- 语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。 - 形式上,Generator函数是一个普通函数,但是有两个特征。一是, function 关键字与函数名之间有一个星号;二是,函数体内部使用 yield 表达式,定义不同的内部状态( yield 在英语里的意思就是“产出”)。
- 由于 Generator 函数返回的遍历器对象,只有调用 next 方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
二、代码
//生成器函数:function关键字和函数名之间有一个*
function* add(){
console.log('start');
let x = yield '2';
console.log('one:'+2);
let y = yield '3';
console.log('two:'+y);
return x+y;
}
// 返回一个遍历器对象
let fn=add();
// next() 恢复执行标志
console.log(fn.next());
// 当 next() 传入参数时,该参数就会被当作上一个 yield 表达式的返回值 ,即 x = 20, y = 3
console.log(fn.next(20));// one:20 {value: '3', done: false}
console.log(fn.next(30));// two:30 {value: '50', done: true}
- 使用场景:为不具备 Iterator 接口的对象提供了遍历操作
- 利用for…of循环,可以写出遍历任意对象(object)的方法。原生的 JavaScript 对象没有遍历接口(不具备 Symbol.iterator方法),无法使用for…of循环,通过 Generator 函数为它加上这个接口,即将 Generator 函数加到对象的Symbol.iterator属性上面,就可以用了。
//Gemerator 生成器函数
function* objectEntries(obj) {
//获取对象的所有key保存到数组
const propKeys = Object.keys(obj);
for (const propkey of propKeys) {
yield [propkey, obj[propkey]]
}
}
const obj = {
book: 'ES6学习',
price: 18
}
// 把 Generator 生成器函数赋值给对象的Symbol.iterator属性, 为该对象加上遍历器接口
obj[Symbol.iterator] = objectEntries;
console.log(obj);//{book: 'ES6学习', price: 18, Symbol(Symbol.iterator):
// objectEntries(obj) 等价于 obj[Symbol.iterator](obj)
for (let [key, value] of objectEntries(obj)) {
console.log(`${key}: $value`);
}
三、Generator 函数的异步应用
Generator 函数在ajax请求的异步应用,让异步代码同步化
Generator 函数在加载页面的异步应用
//Generator 函数在加载页面的异步应用
// 1.加载 Loading...页面
// 2.数据加载完成...(异步操作)
// 3.Loading 关闭掉
function loadUI() {
console.log('加载 Loading...页面');
}
function showData() {
// 模拟数据加载异步操作
setTimeout(() => {
console.log('数据加载完成');
}, 1000);
}
function hideUI() {
console.log('隐藏 Loading...页面');
}
loadUI();
showData();
hideUI();
上述代码执行后效果:
加载 Loading...页面
隐藏 Loading...页面
数据加载完成
实际需求是加载数据完成后才关闭页面,但由于三个函数函数是同步执行的,数据加载需要时间,在数据未加载完成时,就已经隐藏loading页面。通过 Generator 函数可以解决这个问题。
function* load(){
loadUI();
yield showData();
hideUI()
}
const itLoad = load();
itLoad.next();
function loadUI() {
console.log('加载 Loading...页面');
}
function showData() {
// 模拟数据加载异步操作
setTimeout(() => {
console.log('数据加载完成');
itLoad.next();
}, 1000);
}
function hideUI() {
console.log('隐藏 Loading...页面');
}