1. 程式人生 > 其它 >js中的生成器函式

js中的生成器函式

技術標籤:ES6生成器函式

1、入門

function* fn() {
    console.log(1);
    //暫停!
    yield;
    //呼叫next方法繼續執行
    console.log(2);
}
var iter = fn();
iter.next(); //1
iter.next(); //2

生成器解析如下:
1、函式生成器特點是函式名前面有一個‘*’

2、通過呼叫函式生成一個控制器

3、呼叫next()方法開始執行函式

4、遇到yield函式將暫停

5、再次呼叫next() 繼續執行函式

yield關鍵詞並不會像return一樣立即結束函式,只是暫停這個生成器函式,直到下一次呼叫next方法會繼續從yield位置向下執行。

2、訊息傳遞

除了暫停和繼續執行外,生成器同時支援傳值。
在函式的內容可以使用yield的關鍵詞向外返回一個值,在next方法呼叫的時候可以拿到這個值

2.1、Demo1
function* fn() {
    var a = yield 'hello';
    yield;
    console.log(a);
}
var iter = fn();
var res = iter.next();
console.log(res); 
iter.next(2);
iter.next(); //2

在這裡插入圖片描述

解析如下:
1、可以看到,yield後面有一個字串‘hello’,在第一次呼叫next時,暫停在這裡且返回給了iter.next(),即res = {done:false,value:‘hello’}

2、由於暫停的地方是一個賦值語句,需要一個變數給a,於是第二個next()方法中傳了一個引數2替換了yield,最後列印a得到了2。

2.2、demo2
function *foo(x) {
  let y = 2 * (yield (x + 1))
  let z = yield (y / 3)
  return (x + y + z)
}
let it = foo(5)
console.log(it.next())   // => {value: 6, done: false}
console.log(it.next(12)) // => {value: 8, done: false}
console.log(it.next(13)) // => {value: 42, done: true}

分析如下:

  • 首先 Generator 函式呼叫和普通函式不同,它會返回一個迭代器
  • 當執行第一次 next 時,傳參會被忽略,並且函式暫停在 yield (x + 1) 處,所以返回 5 + 1 = 6
  • 當執行第二次 next 時,傳入的引數12就會被當作上一個yield表示式的返回值,如果你不傳參,yield 永遠返回 undefined。此時 let y = 2 * 12,所以第二個 yield 等於 2 * 12 / 3 = 8
  • 當執行第三次 next 時,傳入的引數13就會被當作上一個yield表示式的返回值,所以 z = 13, x = 5, y = 24,相加等於 42

3、生成器函式封裝如下

function ajax(duration) {   
	return new Promise((resolve,reject)=>{
		setTimeout(()=>{
			console.log(duration+'ms延時列印輸出!,當前位於'+ new Date().getSeconds() +'秒')
			resolve(duration);
		},duration)
	})
}
// 生成器函式
function* main() {
	const user = yield ajax(2000);
	console.log('user',user);

	const posts = yield ajax(10000);
	console.log(posts);
}

// 封裝執行生成器函式
function co(generator) {
	const g = generator();
	function handleResult(result) {
		if(result.done) return; //生成器函式結束
		result.value.then(data => {
			    console.log('繼續執行!',data);
				handleResult(g.next(data));
		  },error => {
				g.throw(error);
		  }
		);
	}
	handleResult(g.next());
}

co(main);

輸出結果如下
在這裡插入圖片描述

參考地址:https://blog.csdn.net/qinshengnan520/article/details/108287199