1

I am fetching data from backend service, 20 results at a time. I would like to hide this implementation detail and create a generator that would keep returning records for as long as I need them (while they are available).

Naive implementation:

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!!!
        }
      })
  }
}

(there might be typos - this is simplified code)

I understand why this doesn't work (yield works on innermost function), however I can't seem to find a nice way to create a generator around the async functions.

Is it possible for generator to consume output from async functions?

1
  • 1
    No (unless the caller passes them in via next). But you can use async generators Commented Sep 11, 2018 at 12:00

1 Answer 1

4

As of ES2018, you could use an async generator function:

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

You'd consume that in an async function using for-await-of (not for-of):

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

...or just by calling its next method and awaiting the result:

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

...or of course, in a non-async function, you'd use then on the result of g.next().

Prior to ES2018's async generator function syntax, you'd have to hand-code the generator rather than using function* syntax. Doing so arguably-incorrectly (not allowing for any extensions to %GeneratorPrototype%) is fairly easy. Doing so correctly is fairly awkward, since %GeneratorPrototype% doesn't have a publicly-accessible symbol and you have to go discover it.

Sign up to request clarification or add additional context in comments.

1 Comment

@Bergi True, that would be an easy mistake to make. Done.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.