21.1 概览
两个重要的生成器应用场景是:
- 实现迭代功能
- 阻塞异步函数调用
下面的子节简单介绍了两个应用场景,更详尽的内容在后面讲解(还会讨论其它一些场景)。
21.1.1 通过生成器实现迭代功能
下面的函数返回一个可迭代的对象,每个迭代元素都是一个 [key, value] 对:
// The asterisk after `function` means that
// `objectEntries` is a generator
function* objectEntries(obj) {
let propKeys = Reflect.ownKeys(obj);
for (let propKey of propKeys) {
// `yield` returns a value and then pauses
// the generator. Later, execution continues
// where it was previously paused.
yield [propKey, obj[propKey]];
}
}
关于 objectEntries()
是如何工作的问题在后面讲解。它的使用就像这样:
let jane = { first: 'Jane', last: 'Doe' };
for (let [key,value] of objectEntries(jane)) {
console.log(`${key}: ${value}`);
}
// Output:
// first: Jane
// last: Doe
21.1.2 阻塞异步函数调用
在下面的代码中,我使用流程控制库 co 来异步获取两个 JSON 文件。请注意,行 A 处的执行块直到 Promise.all()
的结果准备就绪之后才会执行。这意味着看起来像是同步的代码却执行了异步的操作。
co(function* () {
try {
let [croftStr, bondStr] = yield Promise.all([ // (A)
getFile('http://localhost:8000/croft.json'),
getFile('http://localhost:8000/bond.json'),
]);
let croftJson = JSON.parse(croftStr);
let bondJson = JSON.parse(bondStr);
console.log(croftJson);
console.log(bondJson);
} catch (e) {
console.log('Failure to read: ' + e);
}
});
getFile(url)
获取 url 指向的文件,具体实现在后面展示,我也将会介绍 co
是如何工作的。