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

results matching ""

    No results matching ""