资讯专栏INFORMATION COLUMN

理解通过thunk函数自动执行generator函数

int64 / 757人阅读

摘要:总结执行方法本质上相当于注册一个回调函数,而函数结合函数就是一种更直观的注册回调函数的方式。函数负责异步执行交出执行权,而函数负责注册回调返回执行权,执行下一步,两者结合从而自动执行函数。

今天又看了一遍阮一峰老师的《Thunk 函数的含义和用法》,这里整理一下自己的理解:

在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成单参数的版本,且只接受回调函数作为参数。

// 正常版本的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 函数封装了两个异步操作。

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返回后,不会自动往下执行,如果写成:

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函数。

如果有任何理解不妥当的地方,欢迎指正交流。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89379.html

相关文章

  • 简单理解Generator执行及async、await语法原理

    摘要:为了更加方便的处理异步操作问题,现在最新的前端框架生态都开始用上了和,有的甚至已经开始使用最新的语法了,这两样都是基于自动执行的原理。这里就简单理解下自执行及语法原理一函数函数指的是能将执行结果传入回调函数,并将该回调函数返回的函数。 为了更加方便的处理异步操作问题,现在最新的前端框架生态都开始用上了Generator和yield,有的甚至已经开始使用最新的async、await语法了...

    stackfing 评论0 收藏0
  • ES6&ES7中的异步之Generator函数与异步编程

    摘要:传统的异步方法回调函数事件监听发布订阅之前写过一篇关于的文章,里边写过关于异步的一些概念。内部函数就是的回调函数,函数首先把函数的指针指向函数的下一步方法,如果没有,就把函数传给函数属性,否则直接退出。 Generator函数与异步编程 因为js是单线程语言,所以需要异步编程的存在,要不效率太低会卡死。 传统的异步方法 回调函数 事件监听 发布/订阅 Promise 之前写过一篇关...

    venmos 评论0 收藏0
  • 关于协程和 ES6 中的 Generator

    摘要:关于协程和中的什么是协程进程和线程众所周知,进程和线程都是一个时间段的描述,是工作时间段的描述,不过是颗粒大小不同,进程是资源分配的最小单位,线程是调度的最小单位。子程序就是协程的一种特例。 关于协程和 ES6 中的 Generator 什么是协程? 进程和线程 众所周知,进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同,进程是 CPU 资源分配的最小单位,...

    RyanHoo 评论0 收藏0
  • Node.js 异步异闻录

    摘要:的异步完成整个异步环节的有事件循环观察者请求对象以及线程池。执行回调组装好请求对象送入线程池等待执行,实际上是完成了异步的第一部分,回调通知是第二部分。异步编程是首个将异步大规模带到应用层面的平台。 showImg(https://segmentfault.com/img/remote/1460000011303472); 本文首发在个人博客:http://muyunyun.cn/po...

    zzbo 评论0 收藏0
  • 再读Generator和Co源码

    摘要:沿用上面的例子,把包装成一个对象这个回调就是等价于通过在里执行回调函数,获取到上一步操作的结果和交回执行权,并把值传递回函数内部,实现了递归执行进一步封装,可以得到以下的代码递归执行 以前看过的内容,感觉忘得差不多,最近抽空又看了一次,果然书读百遍其义自见 Generator的执行 Generator函数可以实现函数内外的数据交换和执行权交换。 从第一次调用next开始,从函数头部开始...

    ernest.wang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<