js中的生成器函式
阿新 • • 發佈:2020-12-19
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