DEV Community

Discussion on: Async Await Behavior

Collapse
peerreynders profile image
peerreynders • Edited on
"asyncFunc is moved into the queue and the program executes the next statement"
Enter fullscreen mode Exit fullscreen mode

That may create the wrong impression with some readers. asyncFunc actually begins to run synchronously until it hits the statement with await. async function is more of a state machine that starts executing synchronously, running until it encounters an awaited promise.

const asyncFunc = async () => {
  console.log('before await');
  console.log(`asyncFunc sees ${await sharedPromise}`)
  console.log('asyncFunc's second statement fires only after sharedPromise has resolved')
}
Enter fullscreen mode Exit fullscreen mode

would result in

before await
first statement after asyncFunc
syncFunc's second statement ...
...
Enter fullscreen mode Exit fullscreen mode

(hinted at in your later linear representation)

Also it's setTimeout that creates a task on the task queue. sharedPromise only is resolved when that scheduled task executes. So the remainder of the asyncFunc function only goes on the microtask queue once sharedPromise has resolved ~1000ms later.


const somePromise = Promise.resolve(42);
const resolve = (value) => console.log(`Resolved to: ${value}`);
const task = () => {
  console.log('before then');
  somePromise.then(resolve);
  console.log('after then');
};
setTimeout(task, 1000);
console.log('task scheduled');
Enter fullscreen mode Exit fullscreen mode
task scheduled
before then
after then
Resolved to: 42
Enter fullscreen mode Exit fullscreen mode

i.e. when chaining, the chained code will always run after the synchronous code - regardless of whether the promise has already settled or not (there is no "checking the queue").

Because the microtask queue always empties before any new events are processed or tasks are run, somePromise has resolved by the time we hit "before then" - so () => resolve(42) can immediately go onto the microtask queue - and resolve will only run once the current call stack empties out.

Collapse
365erik profile image
Erik Smith Author

I take your point on clarity and will have to ponder how to reword some of it without bogging it down with too much detail.

Collapse
peerreynders profile image
peerreynders

I believe the issue is attempting to discuss async/await in isolation of the foundational concepts.

Tasks, microtasks, queues and schedules

  • Foundation: event loop, task, microtask (queues)
  • How promises relate to mictrotasks
  • How async/await relates to promises

In the presence of working knowledge about the event loop, tasks, microtasks, and promises one can call on the pertinent details without getting bogged down in supplementary explanations.

Forming an effective mental model around async/await without understanding the rest is prone to oversimplification that will eventually cause problems (like failing to use functions like Promise.allSettled() and friends).

await vs return vs return await