编辑: 笨蛋爱傻瓜悦 | 2019-07-09 |
1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 目录 Introduction 传统回调 利用 generator 组织异步流程 运行器 并行处理 支持 promise thunk 化 俘获返回值 向 generator 函数传递参数 总结
1 Book 地址 https://yoyoyohamapi.gitbooks.io/-co/content/ 一步步写一个 co 现在,我们有三个 markdown 文件 file1.md,file2.md,file3.md,我们想要统计这三 个文件的大小信息,并输出为以下格式: {file1: 5384, file2: 2712, file3: 13942} 从最传统的回调开始,我们不断优化解决该问题的方式,最后完成了一个简化版的 co V2,实现了用更优雅地方式来组织和编写异步流程. 本文对应的项目地址,包含了文中所有涉及到的代码片: 戳我 Introduction
2 传统的回调 现在,我们有三个 markdown 文件 file1.md 、 file2.md 、 file3.md ,我 们想要统计这三个文件的大小信息,并输出为以下格式: { file1: 5384, file2: 2712, file3:
13942 } 在 Node 中,我们知道 fs.stat 这个异步 API 可以用来获得文件信息,该方法 接受两个参数: path :文件路径;
callback :一个 error-first 型的回调函数. 使用最 传统 的回调方法,我们处理如上问题的代码如下: 传统回调
3 const fs = require('
fs'
);
function error(err) { throw new Error(err);
} function main() { const sizeInfo = { file1'
: 0, file2'
: 0, file3'
:
0 };
fs.stat('
file1.md'
, function(err, stat) { if(err) return error(err);
sizeInfo['
file1'
] = stat.size;
fs.stat('
file2.md'
, function(err, stat) { if(err) return error(err);
sizeInfo['
file2'
] = stat.size;
fs.stat('
file3.md'
, function(err, stat){ if(err) return error(error);
sizeInfo['
file3'
] = stat.size;
console.dir(sizeInfo);
});
} main();
因为是三个文件,我们用传统的回调方式写出了三层的嵌套,整个代码呈现 >
型, 形成了回调地狱(callback hell).如果显示器尺寸不够,甚至需要拖动滚动条才 能阅览整个代码,十分影响编码时的快感.其次,对于熟悉 JAVA,PHP,或者 C++ 语言的开发者,不能用 try-catch 进行错误处理,而需要撰写许多的 if- else 来处理异常或者错误,就更是蛋疼了. 为了从深陷的回调地狱中爬出来,下一节中,我们将使用 ES6 提供的 generator 来 优化异步逻辑. 传统回调
4 传统回调
5 利用generator组织异步流程 generator 概述 generator 是 ES6 中 协程 的实现,用 * 标识的 generator 函数 是其核心, generator 函数 中可以容纳多个流程: function returnTwoAsync() { setTimeout(0, function() { return 2;
});
} function returnThreeAsync() { setTimeout(0, function() { it.next(3);
});
} function *gen() { console.log('
Begin.....'
);
yield 1;
yield returnTwoAsync();
yield returnThreeAsync();
} const it = gen();
// '
Beign....'
it.next();
// {data:1, done:false} it.next();
// {data:undefined, done:false} it.next();
// {data:3, done:false} it.next();
// {data:undefined, done:true} 调用 generator 函数,将返回一个 迭代器(iterator)对象,迭代器对象具有 next() 和 throw() 方法.每次调用 next() ,就能将 generator 由暂停态变 为执行态,并将返回一个执行信息对象,该对象包含了当前阶段的运行结果 value ,以及标识了 generator 是否运行完毕的 done : 利用 generator 组织异步流程