1. 异步操作的同步化表达
- function* main() {
- var result = yield request("http://some.url");
- var resp = JSON.parse(result);
- console.log(resp.value);
- }
- function request(url) {
- makeAjaxCall(url, function(response){
- it.next(response);
- });
- }
- var it = main();
- it.next();
2. 控制流管理 (针对同步任务)
对于层层嵌套的操作, 一般写法
- step1(function (value1) {
- step2(value1, function(value2) {
- step3(value2, function(value3) {
- step4(value3, function(value4) {
- // Do something with value4
- });
- });
- });
- });
使用 Generator 函数
- function* longRunningTask(value1) {
- try {
- var value2 = yield step1(value1);
- var value3 = yield step2(value2);
- var value4 = yield step3(value3);
- var value5 = yield step4(value4);
- // Do something with value4
- } catch (e) {
- // Handle any error from step1 through step4
- }
- }
- // 自动执行
- scheduler(longRunningTask(initialValue));
- function scheduler(task) {
- var taskObj = task.next(task.value);
- // 如果 Generator 函数未结束, 就继续调用
- if (!taskObj.done) {
- task.value = taskObj.value
- scheduler(task);
- }
- }
3. 部署 Iterator 接口
对象是没有 Iterator 接口的, 因为 Generator 函数运行后返回的是一个遍历器对象, 可以利用 Generator 函数为对象部署 Iterator 接口
- function* iterEntries(obj) {
- let keys = Object.keys(obj);
- for (let i=0; i < keys.length; i++) {
- let key = keys[i];
- yield [key, obj[key]];
- }
- }
- let myObj = { foo: 3, bar: 7 };
- for (let [key, value] of iterEntries(myObj)) {
- console.log(key, value);
- }
4.Generator 函数的异步应用
Generator 函数可以暂停执行和恢复执行, 这是它能封装异步任务的根本原因
除此之外, 它还有两个特性, 使它可以作为异步编程的完整解决方案: 函数体内外的数据交换和错误处理机制.
Generator 就是一个异步操作的容器. 它的自动执行需要一种机制, 当异步操作有了结果, 能够自动交回执行权.
两种方法可以做到这一点.
(1) 回调函数. 将异步操作包装成 Thunk 函数, 在回调函数里面交回执行权.
(2)Promise 对象. 将异步操作包装成 Promise 对象, 用 then 方法交回执行权.
4.1 利用 Thunk 函数
在 JavaScript 语言中, 是针对多参数函数, 将其替换成一个只接受回调函数作为参数的单参数函数.
Thunkify 模块
生产环境的转换器, 建议使用 Thunkify 模块, 来实现 Thunk 函数功能.
首先安装 NPM install thunkify
- var fs = require('fs');
- var thunkify = require('thunkify');
- var readFileThunk = thunkify(fs.readFile);
- var g = function* (){
- var f1 = yield readFileThunk('fileA');
- var f2 = yield readFileThunk('fileB');
- // ...
- var fn = yield readFileThunk('fileN');
- };
- // 执行器
- function run(fn) {
- var gen = fn();
- function next(err, data) {
- var result = gen.next(data);
- if (result.done) return;
- result.value(next);
- }
- next();
- }
- run(g);
4.2go 模块
co 模块可以让你不用编写 Generator 函数的执行器.
使用 co 的前提条件是, Generator 函数的 yield 命令后面, 只能是 Thunk 函数或 Promise 对象.
- var gen = function* () {
- var f1 = yield readFile('/etc/fstab');
- var f2 = yield readFile('/etc/shells');
- console.log(f1.toString());
- console.log(f2.toString());
- };
- var co = require('co');
- co(gen);
来源: http://www.jianshu.com/p/21f06de3643c