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----异步的主要内容,如果未能解决你的问题,请参考以下文章