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 是如何工作的。