生成器可以使用异步功能吗?

时间:2018-09-11 11:56:20

标签: javascript generator es6-promise

我正在从后端服务中获取数据,一次20个结果。我想隐藏此实现细节,并创建一个生成器,该生成器将在需要时一直返回记录(在可用时)。

天真的实现:

function* getEndlessRecords(fetchingFunction) {
  const batchSize = 20;

  // endless loop:
  for (let offset = 0; true; offset += batchSize) {
    fetchingFunction(offset, batchSize)
      .then(records => {
        for (let i=0; i < records.length; i++) {
          yield records[i]; // THIS DOESN'T WORK!!!
        }
      })
  }
}

(可能有错别字-这是简化代码)

我了解为什么这不起作用(yield在最里面的函数上起作用),但是我似乎找不到一种很好的方法来围绕异步函数创建生成器。

生成器是否可以使用异步函数的输出?

1 个答案:

答案 0 :(得分:4)

从ES2018开始,您可以使用异步生成器函数

async function* getEndlessRecords(fetchingFunction) {
  const batchSize = 20;

  // endless loop:
  for (let offset = 0; true; offset += batchSize) {
    const records = await fetchingFunction(offset, batchSize);
    for (let i=0; i < records.length; i++) {
      yield records[i];
    }
  }
}

您将使用async(而非for-await-of)在for-of函数中使用它:

for await (const value of getEndlessRecords(/*...*/)) {
    // Do something with `value`
}

...或仅通过调用其next方法并等待结果:

let g = getEndlessRecords(/*...*/);
let result;
while (!(result = await g.next()).done) {
    console.log(result.value);
}

...或者,当然,在非async函数中,您将在then的结果上使用g.next()

在ES2018的异步生成器函数语法之前,您必须手工编码生成器,而不是使用function*语法。可以很容易地做到这一点-正确地 (不允许对%GeneratorPrototype%进行任何扩展)。正确执行此操作相当尴尬,因为%GeneratorPrototype%没有公开可访问的符号,您必须去发现它。