使用Generator函式進行非同步程式設計

2022-08-27 06:54:14 字數 2871 閱讀 2587

generator函式在工作中還沒有用到過,一直在使用async,最近在看async的原理,發現它只是generator的語法糖。

generator的基礎知識之前寫過文章介紹過(這裡主要討論一下怎麼使用generator函式來進行非同步程式設計。

先來看下面的**:

1

function*g()

6 const useg =g();

7useg.next();

8 useg.next();

執行結果:

分析:看下面的**:

1

function*g() , 3000)8}

9 console.log('g end')10}

11 const useg =g();

12 const first =useg.next();

13 first.value(() => useg.next());

執行結果:

分析:我們再來看一下實際的例子,使用generator函式封裝ajax:

1

function*g()

12 xhr.send(null

);13

}14 const families = yield function

(callback) `, true);

17 xhr.responsetype = 'json';

19 xhr.onload = () =>

23 xhr.send(null

);24}25

console.log(families)

26 console.log('g end')27}

28 const useg =g();

29 const first =useg.next();

30first.value(

31 (name) =>

37 );

上面的**執行的是:先通過id取得使用者名稱,再通過使用者名稱取得家庭成員。只看第1行到第27行,步驟清晰,很像是同步的寫法。 

我們需要關注的是,第28行到第37行對generator函式的流程管理:

呼叫generator函式取得迭代器物件

呼叫next方法取得value屬性

呼叫value屬性的值,給它傳入**函式

在**函式中執行第2步,第3步

判斷此時函式已經執行完成

注意到這裡的12345步是可以用迭代來進行的,修改流程管理的**如下:

1

function

run(g)

13//

開始迭代

14loop();15}

16 run(g);

可以看到,使用迭代來管理流程時完全沒有必要知道生成器的內部結構。而且這種方式也不管生成器中有多少個yield。

有一點需要注意的是,使用這種發生來管理流程要求生成器中yield後面的表示式必須是乙個函式,且這個函式有唯一引數(**函式)

其實,我們需要的只是在非同步操作有了結果之後把執行權再交還給generator函式繼續執行。

問題是怎麼知道非同步操作有了結果?

**函式

promise

上面已經介紹過使用**函式來控制流程,它的限制是yield後面的表示式必須是乙個以**函式為引數的函式。

下面介紹使用promise來控制流程:

ajax函式返回promise 

1

function

ajax(url)

12 xhr.send(null

);13}14

)15 }

view code

1

function*g()

8 const useg =g();

9useg.next().value.then(

10 (usernameresponse) =>useg.next(usernameresponse).value.then(

11 (familiesresponse) =>useg.next(familiesresponse)12)

13 );

可以看到:

yield後面必須是promise物件

流程控制中同樣可以使用迭代來執行

promise迭代版本的流程控制:

function

run(g)

//開始迭代

loop();

}run(g);

對比之前的使用**函式來控制流程的**,你會發現和使用promise來控制流程的**如此的類似。

使用promise來控制流程需要注意的是yield後面必須是乙個promise物件

對比使用**函式控制流程和使用promise物件來控制流程

總結:generator函式本身使得非同步操作看起來非常像同步操作,麻煩的是它的流程控制需要我們手動呼叫。(之後要討論的async就是對generator的進一步封裝,不用開發者總結來流程控制)

另外上面的例子為了簡化,都沒有做異常處理,實際開發中,異常處理還是很有必要的。

作成:2019-02-10

修改:2019-02-10 23:23:57 新增分類

參考:《es6標準入門》、《learning typescript》、《深入理解es6》

關於generator函式的理解與使用

關於generator函式的理解與使用 在js中普通function一但建立並呼叫後,直到return,是不會被打斷,而generator函式是es6提供的乙個關於非同步程式設計的解決方案,特點就是generator函式不會返回執行結果,而是便利函式內部的結果或者狀態,通過函式.next 一次次的輸...

Generator函式學習

例子1 const test function x const a test 1 console.log a.next 3 x 2 3 console.log a.next 11 22 3 2 11 3 console.log a.next 2 18 3 2 3 console.log a.next...

迭代函式 Generator函式的理解

一 基本用法 generator函式跟普通函式在寫法上的區別就是,多了乙個星號 並且只有在generator函式中才能使用yield 什麼是yield呢,他相當於generator函式執行的中途暫停點,比如下方有3個暫停點。而怎麼才能暫停後繼續走呢?那就得使用到next方法,next方法執行後會返回...