3

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

2
  • 1
    Just was, no reason, I'm using babel for something else and happened to use it here Commented Jun 5, 2019 at 8:41
  • (For lurkers: The Babel output is also what up-to-date Node.js does with this code natively.) Commented Jun 5, 2019 at 8:51

1 Answer 1

1

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").
Sign up to request clarification or add additional context in comments.

5 Comments

What do you mean by implicit await or return, does an implicit await mean waiting for a promise to resolve?
@tjb - Sorry, the "(implicit or explicit)" referred only to return, I'll see if I can rephrase. An explicit return is, of course, return; or return value;. An implicit return is just code execution reaching the end of the function, as f and outer both do.
@tjb - I've updated to handle that implicit or explicit thing and add more detail.
thanks, I think I'm starting to get this,...but I've thought that alot of times already :)
@tjb - LOL, been there!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.