让人头痛的Generator 函数的异步应用真的有用吗?( 三 )


异步任务的封装下面看看如何使用 Generator 函数 , 执行一个真实的异步任务 。
var fetch = require('node-fetch');function* gen(){var url = '';var result = yield fetch(url);console.log(result.bio);}上面代码中 , Generator 函数封装了一个异步操作 , 该操作先读取一个远程接口 , 然后从 JSON 格式的数据解析信息 。 就像前面说过的 , 这段代码非常像同步操作 , 除了加上了yield命令 。
执行这段代码的方法如下 。
var g = gen();var result = g.next();result.value.then(function(data){return data.json();}).then(function(data){g.next(data);});上面代码中 , 首先执行 Generator 函数 , 获取遍历器对象 , 然后使用next方法(第二行) , 执行异步任务的第一阶段 。 由于Fetch模块返回的是一个 Promise 对象 , 因此要用then方法调用下一个next方法 。
可以看到 , 虽然 Generator 函数将异步操作表示得很简洁 , 但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段) 。
4、Thunk 函数Thunk 函数是自动执行 Generator 函数的一种方法 。
参数的求值策略Thunk 函数早在上个世纪 60 年代就诞生了 。
那时 , 编程语言刚刚起步 , 计算机学家还在研究 , 编译器怎么写比较好 。 一个争论的焦点是"求值策略" , 即函数的参数到底应该何时求值 。
var x = 1;function f(m) {return m * 2;}f(x + 5)上面代码先定义函数f , 然后向它传入表达式x + 5 。 请问 , 这个表达式应该何时求值?
一种意见是"传值调用"(call by value) , 即在进入函数体之前 , 就计算x + 5的值(等于 6) , 再将这个值传入函数f 。 C 语言就采用这种策略 。
f(x + 5)// 传值调用时 , 等同于f(6)另一种意见是“传名调用”(call by name) , 即直接将表达式x + 5传入函数体 , 只在用到它的时候求值 。 Haskell 语言采用这种策略 。
f(x + 5)// 传名调用时 , 等同于(x + 5) * 2传值调用和传名调用 , 哪一种比较好?
回答是各有利弊 。 传值调用比较简单 , 但是对参数求值的时候 , 实际上还没用到这个参数 , 有可能造成性能损失 。
function f(a, b){return b;}f(3 * x * x - 2 * x - 1, x);上面代码中 , 函数f的第一个参数是一个复杂的表达式 , 但是函数体内根本没用到 。 对这个参数求值 , 实际上是不必要的 。 因此 , 有一些计算机学家倾向于"传名调用" , 即只在执行时求值 。
Thunk 函数的含义编译器的“传名调用”实现 , 往往是将参数放到一个临时函数之中 , 再将这个临时函数传入函数体 。 这个临时函数就叫做 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);


推荐阅读