Skip to content

Instantly share code, notes, and snippets.

@domenic
Created June 7, 2017 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save domenic/9c743590125cb5b2fe2bcfb1e93c664a to your computer and use it in GitHub Desktop.
Save domenic/9c743590125cb5b2fe2bcfb1e93c664a to your computer and use it in GitHub Desktop.
Async generator next vs. return

Consider:

async function* f() {
  const x = Promise.resolve(1);
  const y = Promise.resolve(2);
  
  const fromX = yield x;
  return y;
}

const g = f();

const a = Promise.resolve("a");
const b = Promise.resolve("b");

At this point we are suspended at the yield x. Now let's feed a value into the generator:

const result1 = g.next(a);

We require:

  • result1 must be { value: 1, done: false }, because we've decided that yield <-> yield await.
  • fromX === a; we do not unwrap values passed in as arguments to next(), as they are not treated specially.

Now let's do it again:

const result2 = g.next(b);

We require:

  • result2 must be { value: 2, done: false }, because we want return <-> return await; this was not stated explicitly, but makes sense.
  • b is ignored, similar to the result of the last call to .next() on a async generator.

Now let's try something different. Instead of .next(), let's call .return():

const result1 = g.return(a);

The rough meaning of g.return(a) is to turn the current yield statement we're paused on into a return a statement. If we take that literally, this implies we want to require:

  • result1 must be { value: "a", done: true }

This is markedly different from how we behave for g.next(a), where we treated the parameter as opaque. But it falls out of the rough meaning of g.return(a).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment