Sorry in advance for the long post! Below is a code example I'm reviewing and the log outputs:
const a = () => new Promise( resolve => { setTimeout( () => resolve('result of a()'), 1000); }); const b = () => new Promise( resolve => { setTimeout( () => resolve('result of b()'), 500); }); const c = () => new Promise( resolve => { setTimeout( () => resolve('result of c()'), 1100); }); // async generator function const MyAsyncGenerator = async function*() { yield await a(); yield await b(); yield await c(); }; // generator object const gen = MyAsyncGenerator(); // get 'gen' values (async () => { console.log(await gen.next()) console.log(await gen.next()) console.log(await gen.next()) console.log(await gen.next()) })(); (async () => { await Promise.all([a(), b(), c()]).then(res => console.log(res)) })() { value: 'result of a()', done: false } [ 'result of a()', 'result of b()', 'result of c()' ] { value: 'result of b()', done: false } { value: 'result of c()', done: false } { value: undefined, done: true } I'm trying to figure out why Promise.all([...]).then() is logged second. Here's my best explanation but would really appreciate any additional insights:
Since there are two anonymous async IIFEs (Immediately Invoked Function Expressions), while the first
gen.next()evaluates the result ofa(), the.then()method on the new Promise returned byPromise.all()is pushed to the microtask queueAfter the first
await gen.next()is logged to the console, the call stack is empty, so the event loop pushes.then()to the call stack next
I'm ultimately unsure whether it has to do with the task vs. microtask queue or when Promise.all() is fulfilled relative to the generator iterations. My understanding is that setTimeout() goes to the task queue, but if we include Promise.all() in the same code block under the generator iterations, the logs are in order:
(async () => { console.log(await gen.next()) console.log(await gen.next()) console.log(await gen.next()) console.log(await gen.next()) Promise.all([a(), b(), c()]).then(res => console.log(res)) })(); { value: 'result of a()', done: false } { value: 'result of b()', done: false } { value: 'result of c()', done: false } { value: undefined, done: true } [ 'result of a()', 'result of b()', 'result of c()' ]
Promise.all([a(), b(), c()])will resolve after1100ms. The secondgen.next()will be called after1000ms and resolve after an additional500ms -1500ms >1100ms.I'm trying to figure out why Promise.all([...]).then() is logged second> async IIFE's here don't wait for anything. The call toPromise.all()does not wait for any await resolution, because its not using any of the awaited results.awaitspecifically means "leave the current function, and see what else is there to do in the current program". All things happen when their timer hits, nothing in your program chains thatPromise.all()to "after the generator is done".