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

# 2.1 声明与调用

# * 的位置没有限制

function * gen(){
	console.log('hello generator');
}

gen(); // 函数没有执行,而是返回了一个生成器对象
let iterator = gen();
console.log(iterator) //  gen {<suspended>}

iterator.next(); // hello generator  【{value: undefined, done: true}】

# 函数代码分隔符 yield

  • 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到
  • yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
function * gen(){ 
	yield '一只没有耳朵'; 
	yield '一只没有尾巴'; 
	return '真奇怪'; 
} 

let iterator = gen(); 

console.log(iterator.next()); // {value: "一只没有耳朵", done: false}
console.log(iterator.next()); // {value: "一只没有尾巴", done: false}
console.log(iterator.next()); // {value: "真奇怪", done: true}
function * gen(){
	console.log(111);
	yield '一只没有耳朵';
	console.log(222);
	yield '一只没有尾巴';
	console.log(333);
	yield '真奇怪';
	console.log(444);
}

let iterator = gen();

iterator.next(); // 111    【{value: "一只没有耳朵", done: false}】
iterator.next(); // 222    【{value: "一只没有尾巴", done: false}】
iterator.next(); // 333    【{value: "真奇怪", done: false}】
iterator.next(); // 444    【{value: undefined, done: true}】

实际案例1:发号器

function * createIdMaker() {
  let id = 1
  while(true){
    yield id++
  }
}

const idMaker = createIdMaker()
console.log(idMaker.next().value) // 1
console.log(idMaker.next().value) // 2
console.log(idMaker.next().value) // 3

实际案例2:使用 Generator 函数实现 iterator 方法

原来的

const obj = {
  store: ['foo', 'bar', 'baz']
  [Symbol.iterator]: function() {
    let index = 0
    const self = this
    return {
      next: function(){
        return {
          value: self.store[index],
          done: index++ >= self.store.length
        }
      }
    }
  }
}

改进后

const obj = {
  store: ['foo', 'bar', 'baz']
  [Symbol.iterator]: function * () {
    for (const item of this.store){
      yield item
    }
  }
}

# 传递实参

  • next 方法可以传递实参,作为 yield 语句的返回值
function * gen(arg) {
	console.log(arg);
	
	const one = yield 111;
	console.log(one);
	
	const two = yield 222;
	console.log(two);
	
	const three = yield 333;
	console.log(three);
}

let iterator = gen('AAA');

console.log(iterator.next()); // AAA {value: 111, done: false}
console.log(iterator.next('BBB')); // BBB {value: 222, done: false}
console.log(iterator.next('CCC')); // CCC {value: 333, done: false}
console.log(iterator.next('DDD')); // DDD {value: undefined, done: true}

# 生成器函数实例

异步编程实例,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();
	}, 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();
上次更新: 2022/4/21 22:21:34