Andrea Simone Costa
Andrea Simone Costa

Reputation: 1264

Asynchronous Generators in Javascript: is there a difference between yielding a Promise and yielding an awaited Promise?

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?

Upvotes: 1

Views: 176

Answers (2)

Andrea Simone Costa
Andrea Simone Costa

Reputation: 1264

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.

Upvotes: 2

pfeileon
pfeileon

Reputation: 299

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

Upvotes: 0

Related Questions