如何在发电机内使用等待?

时间:2016-03-19 21:07:29

标签: asynchronous async-await ecmascript-6 generator

我有一个生成器,在其他操作中,查询数据库,如

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

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

这是无效的语法。使用承诺并从then屈服也是不可能的。

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

2 个答案:

答案 0 :(得分:11)

Node v10 +(已发布的April 2018Chrome 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);
  }
}());

与常规(非异步)生成器相比,请记住在调用await之前使用.next()。另外,新的for-await-of语法自Node v9.2起可用,并且可以在Node v10中使用而没有任何标志。

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

答案 1 :(得分:-1)

您无法将async与生成器功能结合使用。这说你很可能不想在你的情况下使用生成器而只是有一个异步函数:

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

    return smth;
  }
}

在编译async时,将为您生成生成器