【问题标题】:Can generator use async functions?生成器可以使用异步函数吗?
【发布时间】:2018-09-11 11:56:19
【问题描述】:

我正在从后端服务获取数据,一次 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 适用于最里面的函数),但是我似乎找不到围绕异步函数创建生成器的好方法。

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

【问题讨论】:

  • 否(除非调用者通过next 传递它们)。但是你可以使用async generators

标签: javascript generator es6-promise


【解决方案1】:

从 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];
    }
  }
}

您可以使用 for-await-of(而不是 for-of)在 async 函数中使用它:

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 函数中,您可以在g.next() 的结果上使用then

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

【讨论】:

  • @Bergi 没错,这将是一个容易犯的错误。完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-28
  • 2014-08-06
  • 2011-12-30
  • 1970-01-01
相关资源
最近更新 更多