Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use await inside a generator?

I'm having a generator that, among other operations, queries a database, like

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

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

which isn't valid syntax. Using promises and yielding from a then, isn't possible either.

What should I do then? How can I use asynchronous operation inside a generator?

like image 741
rishat Avatar asked Mar 19 '16 21:03

rishat


People also ask

Can an async function in a generator?

Among those features are generator functions and async/await. Generator functions give you the ability to pause and continue the execution of a program. In contrast, async/await gives you the ability to write asynchronous code without falling into "callback hell", which you risk when writing standard promises.

Does async-await use generators?

Async/await makes it easier to implement a particular use case of Generators. The return value of the generator is always {value: X, done: Boolean} whereas for async functions, it will always be a promise that will either resolve to the value X or throw an error.

How do you use await inside a loop?

You need to place the loop in an async function, then you can use await and the loop stops the iteration until the promise we're awaiting resolves. You could also use while or do.. while or for loops too with this same structure.

Can await be used inside a promise?

The await operator is used to wait for a Promise . It can only be used inside an async function within regular JavaScript code; however it can be used on its own with JavaScript modules.

What is the difference between async and await in a generator?

A generator function is executed yield by yield i.e one yield-expression at a time by its iterator (the next method) whereas async-await, they are executed sequential await by await. Async/await makes it easier to implement a particular use case of Generators .

What is the difference between a generator and a sync-await?

A generator function is executed yield by yield i.e one yield-expression at a time by its iterator (the next method) whereas a sync-await, they are executed sequential await by await. Async/await makes it easier to implement a particular use case of Generators.

How do I use async/await with a function?

For a function to use async/await, it only needs to be declared as async. Here's an example of the fetchUsers function rewritten into a strictly async function (no generator): You can still make this function a generator and pause the function whenever you'd like:

How do you execute the body of a generator function?

When a generator function is called, its body is not executed right away. Instead it returns an iterator-object which adheres to the iterator protocol i.e. it has a next method. The only way to execute the body of gen is by calling the next method on its iterator-object.


1 Answers

Calling await in generators (aka async generators) has been supported natively in Node v10+ (released April 2018) and Chrome since v63, as well as Firefox v57.

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);
  }
}());

Compared to a regular (non-async) generators, remember to use await before calling .next(). Alternatively, the new for-await-of syntax has been available since Node v9.2, and can be used in Node v10 without any flags.

For older versions of node (or for Jest), you can use the Babel plugin transform-async-generator-functions.

like image 155
Dan Dascalescu Avatar answered Oct 16 '22 16:10

Dan Dascalescu