• js-学习笔记-Thunk函数


    Thunk 函数是自动执行 Generator 函数的一种方法。

    编译器的“传名调用”实现,往往是将参数放到一个临时函数之中,再将这个临时函数传入函数体。这个临时函数就叫做 Thunk 函数。

    function f(m) {
      return m * 2;
    }
    
    f(x + 5);
    
    // 等同于
    
    var thunk = function () {
      return x + 5;
    };
    
    function f(thunk) {
      return thunk() * 2;
    }

    上面代码中,函数f的参数x + 5被一个函数替换了。凡是用到原参数的地方,对Thunk函数求值即可。

    这就是 Thunk 函数的定义,它是“传名调用”的一种实现策略,用来替换某个表达式。

    JavaScript 语言的 Thunk 函数

    JavaScript 语言是传值调用,它的 Thunk 函数含义有所不同。在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。

    // 正常版本的readFile(多参数版本)
    fs.readFile(fileName, callback);
    
    // Thunk版本的readFile(单参数版本)
    var Thunk = function (fileName) {
      return function (callback) {
        return fs.readFile(fileName, callback);
      };
    };
    
    var readFileThunk = Thunk(fileName);
    readFileThunk(callback);

    上面代码中,fs模块的readFile方法是一个多参数函数,两个参数分别为文件名和回调函数。经过转换器处理,它变成了一个单参数函数,只接受回调函数作为参数。这个单参数版本,就叫做 Thunk 函数。

    任何函数,只要参数有回调函数,就能写成 Thunk 函数的形式。下面是一个简单的 Thunk 函数转换器。

    // ES6版本
    var Thunk = function(fn) {
      return function (...args) {
        return function (callback) {
          return fn.call(this, ...args, callback);
        }
      };
    };

    使用上面的转换器,生成fs.readFile的 Thunk 函数。

    var readFileThunk = Thunk(fs.readFile);
    readFileThunk(fileA)(callback);

    你可能会问, Thunk 函数有什么用?回答是以前确实没什么用,但是 ES6 有了 Generator 函数,Thunk 函数现在可以用于 Generator 函数的自动流程管理。

    Generator 函数可以自动执行。

    function* gen() {
      // ...
    }
    
    var g = gen();
    var res = g.next();
    
    while(!res.done){
      console.log(res.value);
      res = g.next();
    }

    上面代码中,Generator 函数gen会自动执行完所有步骤。

    Thunk 函数真正的威力,在于可以自动执行 Generator 函数。下面就是一个基于 Thunk 函数的 Generator 执行器。

    function run(fn) {
      var gen = fn();
    
      function next(err, data) {
        var result = gen.next(data);
        if (result.done) return;
        result.value(next);
      }
    
      next();
    }
    
    function* g() {
      // ...
    }
    
    run(g);

    上面代码的run函数,就是一个 Generator 函数的自动执行器。内部的next函数就是 Thunk 的回调函数。next函数先将指针移到 Generator 函数的下一步(gen.next方法),然后判断 Generator 函数是否结束(result.done属性),如果没结束,就将next函数再传入 Thunk 函数(result.value属性),否则就直接退出。

    有了这个执行器,执行 Generator 函数方便多了。不管内部有多少个异步操作,直接把 Generator 函数传入run函数即可。当然,前提是每一个异步操作,都要是 Thunk 函数,也就是说,跟在yield命令后面的必须是 Thunk 函数。

    Thunk 函数并不是 Generator 函数自动执行的唯一方案。因为自动执行的关键是,必须有一种机制,自动控制 Generator 函数的流程,接收和交还程序的执行权。回调函数可以做到这一点,Promise 对象也可以做到这一点。

  • 相关阅读:
    JS实现继承的几种方式
    网站与域名知识扫盲-符号标签大全
    网站与域名知识扫盲
    第八届蓝桥杯决赛 发现环
    1014. Waiting in Line (模拟)
    第八届蓝桥杯决赛 对局匹配
    nvm安装nodejs(安装在非系统盘内)
    jquery datatable 获取当前分页的数据
    高德地图--轨迹回放(一)
    html5shiv.js和respond.js引入不起作用解决
  • 原文地址:https://www.cnblogs.com/zczhangcui/p/6675603.html
Copyright © 2020-2023  润新知