理解經過thunk函數自動執行generator函數

今天又看了一遍阮一峯老師的《Thunk 函數的含義和用法》,這裏整理一下本身的理解:

在 JavaScript 語言中,Thunk 函數替換的不是表達式,而是多參數函數,將其替換成單參數的版本,且只接受回調函數做爲參數。html

// 正常版本的readFile(多參數版本)
fs.readFile(fileName, callback);

// Thunk版本的readFile(單參數版本)
var readFileThunk = Thunk(fileName);
readFileThunk(callback);

var Thunk = function (fileName){
  return function (callback){
    return fs.readFile(fileName, callback); 
  };
};

以讀取文件爲例。下面的 Generator 函數封裝了兩個異步操做。shell

var fs = require('fs');
var thunkify = require('thunkify');
var readFile = thunkify(fs.readFile);

var gen = function* (){
  var r1 = yield readFile('/etc/fstab'); // 2. 讀取文件一
  console.log(r1.toString());
  var r2 = yield readFile('/etc/shells');// 5. 讀取文件二
  console.log(r2.toString());
};

手動執行方式:異步

var g = gen();// 0. 初始化

var r1 = g.next();// 1. 執行下一步,返回的r1就是generator指針:{value, done},而這裏的value其實就是一個thunk函數,這個thunk函數以回調函數做爲參數
r1.value(function(err, data){// 3. 文件一讀取完成的回調函數
  if (err) throw err;
  var r2 = g.next(data);// 4. 執行下一步
  r2.value(function(err, data){ // 文件二讀取完成的回調函數
    if (err) throw err;
    g.next(data);
  });
});

總的來講,其實就是利用thunk函數,把須要作的操做和對應的回調函數,從fn(operation, callback)改爲了fn(operation)(callback)的形式。函數

爲何要這麼作?
是由於generator函數在yield返回後,不會自動往下執行,若是寫成:ui

var gen = function* (){
  var r1 = yield readFile('/etc/fstab', gen.next()); // 這時gen尚未初始化,不是一個generator指針,因此沒有next方法,而gen() !== gen(),因此也不能寫成gen().next()
  console.log(r1.toString());
};

也無法自動執行,因此將回調函數分離到第二步,而後在回調函數裏(這時generator確定已經初始化完了,否則無法執行到回調函數)執行generator指針的next方法,走到下一步。指針


總結:執行value方法本質上至關於註冊一個回調函數,而generator函數結合thunk函數就是一種更直觀的註冊回調函數的方式。generator函數負責異步執行(交出執行權),而thunk函數負責註冊回調(返回執行權,執行下一步),二者結合從而自動執行generator函數。code

若是有任何理解不穩當的地方,歡迎指正交流。htm

相關文章
相關標籤/搜索