1

I'm taking a look at the asynchronous generators proposed in ES9 to be able to grasp the logic.

Since each yielded value is used as value property in the returned object - wrapped by a Promise - from a next() call:

async function * asyncGen() {
    yield 1;
    yield 2; 
}

let asyncIterator = asyncGen();

asyncIterator.next(); // Promise fullfilled with {value: 1, done: false}

asyncIterator.next(); // Promise fullfilled with {value: 2, done: false}

I thought this was true also for yielded Promises:

async function * asyncGen() {
    yield Promise.resolve(3);
    yield new Promise(done => setTimeout(done, 10000));
}

let asyncIterator = asyncGen();

asyncIterator.next();
// Expected: Promise fullfilled with {value: Promise fullfilled with 3, done: false}
// Get: Promise fullfilled with {value: 3, done: false}

asyncIterator.next();
// Expected: Promise fullfilled with
// {value: Promise pending for 10 seconds, then fullfilled with undefined, done: false}
// Get: Promise pending for 10 seconds,
// then fullfilled with {value: undefined, done: false}

So the promises are merged together. This doesn't sound bad, but I don't expected that because of:

async function * asyncGen() {
    yield await Promise.resolve(3);
    yield await new Promise(done => setTimeout(done, 10000));
}

let asyncIterator = asyncGen();

asyncIterator.next(); // Promise fullfilled with {value: 3, done: false}

asyncIterator.next(); 
// Promise pending for 10 seconds,
// then fullfilled with {value: undefined, done: false}

Here merging is more reasonable because await cannot stop the generator, next() call have to return a Promise. But that Promise could be fullfilled only when the awaited Promise into the generator is fullfilled.

So is the keyword await completely useless used with the keyword yield in the same expression or am I missing something important?

Andrea Simone Costa
  • 1,164
  • 6
  • 16
  • 1
    Yes, it appears useless, just like [`return await`](https://stackoverflow.com/q/43353087/1048572). This is because we [can't have a promise for a promise](https://stackoverflow.com/q/32168194/1048572), which would be weird in `for await (… of …)`. – Bergi Sep 10 '18 at 19:30

2 Answers2

2

Async generators unwrap yielded promises to avoid a promise (the one returned by the next method, for example) of promise (the one inside the value field). A concept from which the JavaScript lang always kept away.

Andrea Simone Costa
  • 1,164
  • 6
  • 16
0

One interesting aspect of combining await and yield is that await can’t stop yield from returning a Promise, but it can stop that Promise from being settled:

async function* asyncGenerator() {
    console.log('Start');
    const result = await doSomethingAsync(); // (A)
    yield 'Result: '+result; // (B)
    console.log('Done');
}

ES2018: asynchronous iteration by Dr. Axel Rauschmayer

pfeileon
  • 290
  • 1
  • 17
  • Thanks but I'm not speaking about this particular case. I agree with the possibility of stopping the returned promise using await, because is the only reasonable thing that could happen. – Andrea Simone Costa Sep 10 '18 at 15:19