ES6 |Generator函数的异步应用

在这里插入图片描述

协程

多个线程互相协作,完成异步任务。yield命令表示执行到此处,执行权将交给其他协程,也就是说,yield命令是异步两个阶段的分界线。协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行。

function *asyncJob() {
  // ...其他代码
  var f = yield readFile(fileA);
  // ...其他代码
}

Generator 函数实现协程

function* gen(x) {
  var y = yield x + 2;
  return y;
}

var g = gen(1);	//返回一个遍历器对象 不返回结果
//指向yield并执行,value是后面表达式的值。next方法的作用是分阶段执行Generator函数
g.next() // { value: 3, done: false }	
g.next() // { value: undefined, done: true }

Generator 函数的数据交换和错误处理

  • next接受参数进行数据交换
    next返回值的value属性,是 Generator 函数向外输出数据;next方法还可以接受参数,向 Generator 函数体内输入数据。next接受的参数会被当做上一个yield的返回结果

    function* gen(x) {
      var y = yield x + 2;
      return y;
    }
    
    var g = gen(1);	
    g.next() // { value: 3, done: false }	
    g.next(2) // { value: undefined, done: true } 
    //在这里传入的2会被当做是上一个yield的返回结果,即yield x+2等于2,这个时候y=2并返回
    
  • 错误处理

    Generator 函数体外,使用指针对象的throw方法抛出的错误,可以被函数体内的try...catch代码块捕获

    function* gen(x){
      try {
        var y = yield x + 2;
      } catch (e){
        console.log(e);
      }
      return y;
    }
    
    var g = gen(1);
    g.next();
    g.throw('出错了');
    // 出错了
    

异步任务的封装

var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url); //fetch读取接口,返回一个 Promise 对象
  console.log(result.bio);
}

var g = gen();
var result = g.next();	//执行fetch(url),返回具有value和done属性的result对象

//在这里value相当于fetch返回的Promise对象,data就是接口返回的结果
result.value.then(function(data){	
  return data.json();
}).then(function(data){
  g.next(data);
});

Thunk 函数

背景:函数参数的求值策略

var x = 1;
function f(m){
  return m * 2;
}
f(x + 5)

//1. 传值调用
在进入函数体前就先计算x+5,成f(6),6再传进去执行,即6*2
//2. 传名调用
直接将表达式x+5传入,即(x+5)*2

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;
}

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

function f(a, cb) {
  cb(a);
}
let ft = Thunk(f);	//转交给Thunk暂存

let log = console.log.bind(console);	//会作为表达式放进去而不会立即执行
ft(1)(log) // 1	

Thunkify 模块

生产环境的转换器,建议使用 Thunkify 模块。首先安装模块

$ npm install thunkify

使用

var thunkify = require('thunkify');
var fs = require('fs');

var read = thunkify(fs.readFile);
read('package.json')(function(err, str){
  // ...
});

co模块

用于 Generator 函数的自动执行,

这个 Generator 函数用于依次读取两个文件

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

co 模块可以让你不用编写 Generator 函数的执行器

var co = require('co');
co(gen);

co函数返回一个Promise对象,因此可以用then方法添加回调函数

co(gen).then(function (){
  console.log('Generator 函数执行完成');
});
posted @ 2020-09-01 13:53  sanhuamao  阅读(137)  评论(0编辑  收藏  举报