Generator + co

Generator

Generator 函數是一個普通函數。

區別:

  1. function關鍵字與函數名之間有一個星號。(ES6 沒有規定,function關鍵字與函數名之間的星號,寫在哪個位置都能通過。)
  2. 函數體內部使用yield表達式,定義不同的內部狀態(yield在英語裏的意思就是“產出”)。
  3. 調用 Generator 函數後,該函數並不執行,返回的也不是函數運行結果,而是一個指向內部狀態的指針對象,也就是遍歷器對象(Iterator Object)。必須調用遍歷器對象的 next() 方法,使得指針移向下一個狀態
 function * helloWorldGenerator() {
     yield console.log('hello');
     yield console.log('world');
     return console.log('ending');
}

var hw = helloWorldGenerator();

— 控制檯輸入 hw.next();

hw.next();
index.html:156 hello

hw.next();
index.html:157 world

hw.next();
index.html:158 ending

必須調用遍歷器對象的 next() 方法,使得指針移向下一個狀態。每次調用next方法,內部指針就從上一次停下來的地方開始執行,直到遇到下一個yield表達式(或return語句)爲止。

換言之,Generator 函數是分段執行的,yield表達式是暫停執行的標記,而next方法可以恢復執行。

上面代碼定義了一個 Generator 函數helloWorldGenerator,它內部有兩個yield表達式(hello和world),即該函數有三個狀態:hello,world 和 return 語句(結束執行)。

yield 表達式

由於 Generator 函數返回的遍歷器對象,只有調用next方法纔會遍歷下一個內部狀態,所以其實提供了一種可以暫停執行的函數。yield表達式就是暫停標誌。

next方法

(1)遇到yield表達式,就暫停執行後面的操作,並將緊跟在yield後面的那個表達式的值,作爲返回的對象的value屬性值。

(2)下一次調用next方法時,再繼續往下執行,直到遇到下一個yield表達式。

(3)如果沒有再遇到新的yield表達式,就一直運行到函數結束,直到return語句爲止,並將return語句後面的表達式的值,作爲返回的屬性值。

(4)如果該函數沒有return語句,則返回的對象的value屬性值爲undefined。

yield表達式後面的表達式,只有當調用next方法、內部指針指向該語句時纔會執行,因此等於爲 JavaScript 提供了手動的“惰性求值”(Lazy Evaluation)的語法功能。

用途:

ajax的異步處理,需要等待別的異步成功後再執行

function* main() {
	...
    var result = yield request("http://www.xxx.com?rows=10&f={firstName}");
    console.log(result);
    //do 別的ajax請求;
}

co 是什麼

co是用來自動執行generator函數的工具。generator的好處是可以在定義函數時候就打上“斷點”,調用函數時候可以在斷點的地方暫停函數的執行。Generator帶來的問題是如何控制什麼時候進行下一步調用。co可以解決這個問題。

特點:

1、co 模塊,它基於 ES6 的 generator 和 yield ,能用同步的形式編寫異步代碼的nodejs模塊。

代碼如下:

const co = require ('co');

function* main() {
    執行代碼。。。
});

co(main);

co 模塊可以將異步解改成同步。co 函數接受一個 generator 函數作爲參數,在函數內部自動執行 yield 。

co實現generator自動執行的條件

需要yield後面的數據類型爲:

  • promises
  • thunks (functions)
  • array (parallel execution)
  • objects (parallel execution)
  • generators (delegation)
  • generator functions (delegation)

最後兩種類型是官方建議避免使用的。

使用:

安裝:

$ npm install co

index.js

function* helloWorldGenerator() {
   var a = Promise.resolve(1);
   var b = Promise.resolve(2);
   var c = Promise.resolve(3);
   var res = yield [a, b, c];
   console.log(res);
}

co(helloWorldGenerator).catch(onerror);
// 執行: [1, 2, 3]

function onerror(err) {
   console.error(err);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章