【问题标题】:How do I use await inside a generator?如何在生成器中使用 await?
【发布时间】:2016-07-06 13:16:20
【问题描述】:

我有一个生成器,除了其他操作之外,它还可以查询数据库,例如

function* current(db) {
  const items = await db.collection('...').find({ ... });

  for (const item of items)
    if (...) yield item;
}

这不是有效的语法。从then 使用promise 和yield 也是不可能的。

那我该怎么办?如何在生成器中使用异步操作?

【问题讨论】:

  • 不,你不能在 ES6 和 ES7 中将 async 与生成器函数结合起来。
  • 当然不能。但是有可能完全解决我的问题吗?我想做一个依赖数据库的生成器,从数据库中获取数据是一个异步操作。那我就别无选择了吗?
  • 有一些关于如何使这些事情起作用的 ES 提案。看看github.com/kriskowal/gtor。你可以自己手工制作,甚至可以使用awaityield,但我想它不会太简单或太干净。
  • 公平地说,现在有可能在 Node 10 中制作异步生成器,所以它解决了我遇到的问题,尽管我不确定我是否有一个足够通用和足够常见的问题对现在。
  • @rm-:我有同样的问题(因此是赏金):await 是数据库调用的结果,然后从循环中产生结果。

标签: asynchronous async-await ecmascript-6 generator


【解决方案1】:

Node v10+(发布April 2018)和Chrome since v63, as well as Firefox v57原生支持在生成器(又名异步生成器)中调用await

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function getAsyncData() {
  await sleep(1000);  // simulate database/network delay...
  return [1, 2, 3, 4, 5];  // ...then return some data
}

// async generator
async function* filterAsyncData() {
  const items = await getAsyncData();  // await call in generator
  
  for (const item of items)
    if (item % 2) yield item;
}

(async function main() {
  // for-await syntax
  for await (const filteredItem of filterAsyncData())
    console.log(filteredItem);
  
  // classic iterator syntax
  const fadIt = filterAsyncData();
  while (true) {
    const result = await fadIt.next();  // note await
    if (result.done) break;
    console.log(result.value);
  }
}());

与常规(非异步)生成器相比,请记住在调用 .next() 之前使用 await。或者,新的 for-await-of 语法从 Node v9.2 开始可用,并且可以在 Node v10 中使用而无需任何标志。

对于旧版本的节点(或 Jest),您可以使用 Babel 插件transform-async-generator-functions

【讨论】:

  • 我想就是这样!
【解决方案2】:

您不能将 async 与生成器函数结合使用。也就是说,您很可能不想在您的情况下使用生成器,而是只使用 async 函数:

async function current(db) {
  while (true) {
    const latest = await db.collection('messages').findOne({}, {
      sort: {
        timestamp: -1
      }
    });

    return smth;
  }
}

async 被转译时,生成器将为你生成

【讨论】:

  • 我只是想指出你可以在 Babel 5 中。Babel 6 直到最近才支持这个......我相信 6.17.0。
  • 这个while (true)循环没有意义,你的函数returns在第一次迭代中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-23
  • 2019-05-30
  • 2023-03-27
  • 2022-10-19
  • 2021-08-26
  • 2019-09-24
  • 1970-01-01
相关资源
最近更新 更多