[node] Thunk、co模块

#

Thunk

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

#

var thunk = function () {
  return x + 5;
};

function f(thunk){
  return thunk() * 2; }

 


JavaScript是传值调用。
在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); }; };

 

#自制简单的Thunk函数转换器

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

// ES5版本
var Thunk = function(fn){ return function (){ var args = Array.prototype.slice.call(arguments); return function (callback){ args.push(callback); return fn.apply(this, args); } }; }; // ES6版本 var Thunk = function(fn) { return function (...args) { return function (callback) { return fn.call(this, ...args, callback); } }; };

 

#Generator 结合 Thunk 的流程管理

var fs = require('fs');
var thunkify = require('thunkify'); var readFile = thunkify(fs.readFile); var gen = function* (){ var r1 = yield readFile('/etc/fstab'); console.log(r1.toString()); var r2 = yield readFile('/etc/shells'); console.log(r2.toString()); }; var g = gen();//变量g是Generator函数的内部指针,表示目前执行到哪一步。 var r1 = g.next();//next方法负责将指针移动到下一步,并返回该步的信息(value属性和done属性)。 r1.value(function(err, data){ if (err) throw err; var r2 = g.next(data); r2.value(function(err, data){ if (err) throw err; g.next(data); }); });

 

Thunk函数的自动流程管理

#Generator的自动执行器

var fs = require('fs');
var thunkify = require('thunkify'); var readFile = thunkify(fs.readFile); function run(fn) { var gen = fn(); function next(err, data) { var result = gen.next(data); if (result.done) return; result.value(next); } next(); } var gen = function* (){ var f1 = yield readFile('fileA');//要保证yield后边是thunk函数 var f2 = yield readFile('fileB'); // ... var fn = yield readFile('fileN'); }; run(gen);//只要执行run函数,这些操作就会自动完成

 

 


co模块

co模块用于Generator函数的自动执行。
可以让你不用编写Generator函数的执行器。
co函数返回一个Promise对象,因此可以用then方法添加回调函数。
co模块其实就是将两种自动执行器(Thunk函数和Promise对象),包装成一个模块。
使用co的前提条件是,Generator函数的yield命令后面,只能是Thunk函数或Promise对象。

co支持并发的异步操作,即允许某些操作同时进行,等到它们全部完成,才进行下一步。

#基本用法

var co = require('co');

var gen = function* (){
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

//co(gen);//自动执行
co(gen).then(function (){
  console.log('Generator 函数执行完成');
});

 

#基于Promise对象的自动执行

var fs = require('fs');

var readFile = function (fileName){
  return new Promise(function (resolve, reject){
    fs.readFile(fileName, function(error, data){
      if (error) reject(error);
      resolve(data);
    });
  });
};

var gen = function* (){
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

//手动执行//

var g = gen();

g.next().value.then(function(data){
  g.next(data).value.then(function(data){
    g.next(data);
  });
});
////


//自动执行器//

function run(gen){
  var g = gen();

  function next(data){
    var result = g.next(data);
    if (result.done) return result.value;
    result.value.then(function(data){
      next(data);
    });
  }

  next();
}

run(gen);
////



#处理并发的异步操作
把并发的操作都放在数组或对象里面,跟在yield语句后面。

// 数组的写法
co(function* () {
  var res = yield [
    Promise.resolve(1),
    Promise.resolve(2)
  ];
  console.log(res);
}).catch(onerror);

// 对象的写法
co(function* () {
  var res = yield {
    1: Promise.resolve(1),
    2: Promise.resolve(2),
  };
  console.log(res);
}).catch(onerror);

 


#三个somethingAsync异步操作,等到它们全部完成,才会进行下一步。

co(function* () {
  var values = [n1, n2, n3];
  yield values.map(somethingAsync);
});

function* somethingAsync(x) {
  // do something async
  return y
}

 

#co.wrap()

//读取文件1
co(function* (){
  var filename = yield readFile('hello1.txt', 'utf-8');
  return filename;
}).then(console.log, console.error);
//读取文件2
co(function* (){
  var filename = yield readFile('hello2.txt', 'utf-8');
  return filename;
}).then(console.log, console.error);

//使用co.wrap()
var getFile = co.wrap(function* (file){
  var filename = yield readFile(file, 'utf-8');
  return filename;
});
getFile('hello.txt').then(console.log);
getFile('hello2.txt').then(console.log);

 

转载于:https://www.cnblogs.com/qingmingsang/articles/5556204.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值