13.生成器

 

1.生成器

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同

语法说明:

  1. *的位置没有限制
  2. 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值
  3. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
  4. next 方法可以传递实参,作为 yield 语句的返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function * gen() {
console.log(111);
yield 'first yield';
console.log(222);
yield 'second yield';
console.log(333);
yield 'third yield';
console.log(444);
}

let iter = gen();
iter.next();
iter.next();
iter.next();
iter.next();
iter.next();
iter.next();
/**
* 111
* 222
* 333
* 444
* 不会有多余的undefined输出,输出4个结果
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function * gen() {
yield 'first yield';
yield 'second yield';
yield 'third yield';
}

let iter = gen();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
/**
* {value: 'first yield', done: false}
* {value: 'second yield', done: false}
* {value: 'third yield', done: false}
* {value: undefined, done: true}
* {value: undefined, done: true}
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function * gen() {
yield 'first yield';
yield 'second yield';
yield 'third yield';
}

let iter = gen();

for(let e of iter) {
console.log(e);
}
/**
* first yield
* second yield
* third yield
*/

2.生成器函数参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function * gen(param) {
console.log(param);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}

let iterator = gen('AAA');
console.log(iterator.next());
// 第二个next()的参数,作为第一个yield的返回值
console.log(iterator.next('BBB'));
// 第三个next()的参数,作为第二个yield的返回值
console.log(iterator.next("CCC"));
// 第四个next()的参数,作为第三个yield的返回值
console.log(iterator.next("DDD"));

/**
* AAA
* {value: 111, done: false}
* BBB
* {value: 222, done: false}
* CCC
* {value: 333, done: false}
* DDD
* {value: undefined, done: true}
*/

3.生成器函数实例

异步编程

1秒钟后输出111,然后2秒钟后输出222,然后3秒钟后输出333

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 方法一:使用回调函数
setTimeout(()=>{
console.log(111);
setTimeout(()=>{
console.log(222);
setTimeout(()=>{
console.log(333);
}, 3000);
}, 2000);
}, 1000)
/**
* 111
* 222
* 333
*/

// 方法二:使用生成器方法
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000);
}

function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000);
}

function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000);
}

function * gen() {
yield one();
yield two();
yield three();
}

let iterator = gen();
iterator.next();
/**
* 111
* 222
* 333
*/

异步执行的函数传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function getUserInfo() {
setTimeout(() => {
let userData = 'user data';
iterator.next(userData);
}, 1000);
}

function getOrderInfo(userData) {
setTimeout(() => {
console.log("userData=" + userData);
let orderData = 'order data';
iterator.next(orderData);
}, 1000);
}

function getCommodityInfo(orderData) {
setTimeout(() => {
console.log("orderData=" + orderData);
let CommodityData = 'commodity data';
iterator.next(CommodityData);
}, 1000);
}

function * gen() {
let userInfo = yield getUserInfo();
let orderInfo = yield getOrderInfo(userInfo);
let commodityInfo = yield getCommodityInfo(orderInfo);
console.log(commodityInfo);
}

let iterator = gen();
iterator.next();

/**
* userData=user data
* orderData=order data
* commodity data
*/