十二、生成器
大约 3 分钟约 752 字
(一)生成器简介
ES5
异步编程使用纯回调函数node
fs
ajax
mongodb
- 一层套一层,形成回调地狱
- 生成器是一个函数,是
ES6
提供的一种异步编程解决方案- 语法行为与传统函数完全不同
1.声明生成器函数
*
位置可以不同- 直接调用生成器函数无法执行
- 因为本质是一个迭代器对象
- 需要执行
next()
函数才可以调用
// function * gen1(){}
// function* gen2(){}
// function *gen3(){}
function* gen() {
console.log("Hello generator.");
}
let iterator = gen();
console.log(iterator);
// gen {<suspended>}
iterator.next();
// Hello generator.
2.yield 语句
- 生成器函数内部可以出现
yield
语句 yield
是函数代码的分隔符
function* gen() {
console.log(111);
yield "一只没有耳朵";
console.log(222);
yield "一只没有尾巴";
console.log(333);
yield "真奇怪";
console.log(444);
}
let iterator = gen();
console.log(iterator);
iterator.next();
// 111
iterator.next();
// 222
iterator.next();
// 333
iterator.next();
// 444
3.遍历
function* gen() {
yield "一只没有耳朵";
yield "一只没有尾巴";
yield "真奇怪";
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
for (let v of gen()) {
console.log(v);
}
(二)生成器函数参数
next()
方法可以传入实参- 第二次调用
next()
方法传入的参数将作为第一个yield
语句的整体返回结果 - 第三次调用
next()
方法传入的参数将作为第二个yield
语句的整体返回结果 - 第四次调用
next()
方法传入的参数将作为第三个yield
语句的整体返回结果
function* gen(arg) {
console.log(arg); //AAA
// yield 111;
let one = yield 111;
console.log(one); //BBB
// yield 222;
let two = yield 222;
console.log(two); //CCC
// yield 333;
let three = yield 333;
console.log(three); //DDD
}
// 执行获取迭代器对象
let iterator = gen("AAA");
console.log(iterator.next());
// {value: 111, done: false}
console.log(iterator.next("BBB"));
// {value: 222, done: false}
console.log(iterator.next("CCC"));
// {value: 333, done: false}
console.log(iterator.next("DDD"));
// {value: undefined, done: true}
(三)案例实操
- 异步编程
JS
本身是异步单线程编程的,很多操作都是异步实现
- 如:文件 I/O 操作、网络操作(ajax、request)、数据库操作等
1.实现 1s 后控制台输出 111,2s 后输出 222,3s 后输出 333
// 回调地狱
setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
}, 3000);
}, 2000);
}, 1000);
// 生成器函数
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
// 222
}, 1000);
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
// 333
}, 2000);
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000);
}
function* gen() {
yield one();
yield two();
yield three();
}
// 调用生成器函数
let iterator = gen();
iterator.next();
// 111
2.模拟获取以下数据:用户数据、订单数据、商品数据
- 有用户数据才有订单数据,再有商品数据
function getUsers() {
setTimeout(() => {
let data = "用户数据";
// 调用next方法,并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrders() {
setTimeout(() => {
let data = "订单数据";
iterator.next(data);
}, 1000);
}
function getGoods() {
setTimeout(() => {
let data = "商品数据";
iterator.next(data);
}, 1000);
}
function* gen() {
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
let iterator = gen();
iterator.next();
// 以下调用不符合实际场景,因为数据之间有依赖关系
// getUsers();
// getOrders();
// getGoods();