理解经过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

相关文章
相关标签/搜索