tjb
tjb

Reputation: 11728

State of Macrotask and Microtask queue during this calculation

This question is very similar in intent to Difference between microtask and macrotask within an event loop context, but more specific, in that it asks for the explication of a definite example: I think for this reason it shouldn't be considered a duplicate.

What is the state Macrotask queue and Microtask queue during the execution of this code in node.js

console.log("A1");

(async ()=> {

    console.log("1")

    f = async ()=>{console.log('2')}

    await f()

    console.log("3")

})()

console.log("A2");

Output:

A1
1
2
A2
3

Output I expected: A1, A2, '1','2','3'

Based on this reasoning: log A1 --> enqueue anonymous function on microtask queue --> log A2 --> execute anaonymous function log 1, enqueue f on the microtask queue --> execute f from microtask queue --> log 2 --> log 3

Where am I going wrong? (additionally how is a top level async func enqueued?)

NOTE: actual command used to run this was npx babel-node myscript.js

Upvotes: 3

Views: 160

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075337

You're seeing this behavior because an async function runs synchronously up until the first await, explicit return, or implicit return (code execution falling off the end of the function).

I'm going to change the code slightly to give the outer async function a name so it's easier to talk about:

console.log("A1");
const outer = async () => {
    console.log("1")
    f = async ()=>{console.log('2')}
    await f()
    console.log("3")
};
outer();
console.log("A2");

Here's what happens:

  1. console.log("A1") runs (of course).
  2. outer() is called.
  3. The synchronous part of outer runs, so it:
    • Runs the console.log("1")
    • Creates f
    • Calls f()
  4. The synchronous part of f runs, so it:
    • Does console.log('2')
  5. At this point, f implicitly returns, and so it returns its promise to outer. That promise is already fulfilled with the value undefined. (See here in the spec.)
  6. outer awaits f's promise, so it returns its promise to the caller (which throws it away, but that doesn't matter).
  7. outer awaiting f's promise queued a microtask to continue outer because f's promise is already settled.
  8. console.log("A2") runs.
  9. The microtask runs, allowing outer to continue and do console.log("3").

Upvotes: 1

Related Questions