Co-使用co自動化執行Generator函數

co是如何工作的

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

下面所有代碼可以到github上查看源代碼。

fs = require('fs');
co = require('co');

//thunkify是一個nodejs庫,下面我會展示其簡單的實現原理,如果這步你看不懂,可以暫時認爲readFile爲一個普通函數
var readFile = thunkify(fs.readFile);

var gen = function* (){
  var r1 = yield readFile('./hi.txt');
  console.log(r1.toString());
  var r2 = yield readFile('./hello.txt');
  console.log(r2.toString());
};
var gen2 = function* (){
  var r1 = yield 1;
  console.log(r1.toString());
  var r2 = yield 2;
  console.log(r2.toString()); 
};

console.log('------------------run co--------------------');
console.log('-----------gen------------');
co(gen);
console.log('-----------gen2-----------');
co(gen2);

執行結果:
這裏寫圖片描述

由這個執行結果我們至少可以看出兩點:1)普通的generator是不能放到co裏進行自動執行的(gen2沒有自動執行) 2)co可以實現異步執行(三個console前後打出,才返回gen執行的結果)

那麼,什麼樣的generator纔可以被co包裹後自動執行?

co實現generator自動執行的條件

co的github說的很明白,需要yield後面的數據類型爲:

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

最後兩種類型是官方建議避免使用的。array或者object的每個子元素依然應該是promises或者thunks。瞭解promise
thunk在javascript中可以理解爲,可以將一個進行一定操作並調用一個回調函數的函數(nodejs中很多,如:fs),拆分成兩步。上面例子中的thunkify就是一個thunk,其聲明如下:

function thunkify(fn){
  return function(){
    var args = new Array(arguments.length);
    var ctx = this;

    for(var i = 0; i < args.length; ++i) {
      args[i] = arguments[i];
    }

    return function(done){
      var called;

      args.push(function(){
        if (called) return;
        called = true;
        done.apply(null, arguments);
      });

      try {
        fn.apply(ctx, args);
      } catch (err) {
        done(err);
      }
    };
  };
}

執行var readFile = thunkify(fs.readFile);的時候,返回一個函數readFile,其接受一個參數,爲要讀取文件的地址,並再次返回一個函數,該函數的參數爲讀取文件完畢後要執行的回調函數,傳入回調函數後讀取操作纔開始執行。thunk就是把回調函數的寫法變成兩次傳參而已。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章