ES6知识点整理之----Generator----异步

Posted adhehe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6知识点整理之----Generator----异步相关的知识,希望对你有一定的参考价值。

所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

1、异步编程的方法:

  • 回调函数
  • 事件监听
  • 发布/订阅
  • Promise 对象
  • Generator函数

2、为什么 Node 约定,回调函数的第一个参数,必须是错误对象err(如果没有错误,该参数就是null)?

原因是执行分成两段,第一段执行完以后,任务所在的上下文环境就已经结束了。在这以后抛出的错误,原来的上下文环境已经无法捕捉,只能当作参数,传入第二段。

3、Promise 对象就是为了解决 “回调函数地狱”问题而提出的,不是新的语法功能,而是一种新的写法。允许将回调函数的嵌套,改成链式调用。Promise 的最大问题是代码冗余,原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆then,原来的语义变得很不清楚。

4、Generator函数,它的奥妙就在其中的yield命令,它是异步两个阶段的分界线。整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明。

5、Generator 函数可以作为异步编程的完整解决方案,有3个特性

  • 可以暂停执行和恢复执行
  • 函数体内外的数据交换:next返回值的 value 属性,是 Generator 函数向外输出数据;next方法还可以接受参数,向 Generator 函数体内输入数据。
  • 错误处理机制

6、异步任务的封装

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

//封装
function* gen(){
  var url = ‘https://api.github.com/users/github‘;
  var result = yield fetch(url);
  console.log(result.bio);
}

//执行
var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

 

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

 

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

任何函数,只要参数有回调函数,就能写成 Thunk 函数的形式。

 

Generator 函数的流程管理

var fs = require(‘fs‘);
var thunkify = require(‘thunkify‘);
var readFileThunk = thunkify(fs.readFile);

var gen = function* (){
  var r1 = yield readFileThunk(‘/etc/fstab‘);
  console.log(r1.toString());
  var r2 = yield readFileThunk(‘/etc/shells‘);
  console.log(r2.toString());
};


var g = gen();

var r1 = g.next();
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 函数的自动流程管理

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

跟在yield命令后面的必须是 Thunk 函数。

var g = function* (){
  var f1 = yield readFileThunk(‘fileA‘);
  var f2 = yield readFileThunk(‘fileB‘);
  // ...
  var fn = yield readFileThunk(‘fileN‘);
};

run(g);

 

co 模块

一个小工具,用于 Generator 函数的自动执行。

 

以上是关于ES6知识点整理之----Generator----异步的主要内容,如果未能解决你的问题,请参考以下文章

ES6知识点整理之----Generator----异步

ES6知识点整理之----对象扩展

ES6知识点整理之----Proxy----API

ES6知识点整理之----Proxy----this

ES6知识点整理之----async----语法

ES6知识点整理之----正则表达式扩展