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

tjb
  • 11,480
  • 9
  • 70
  • 91

1 Answers1

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").
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • What do you mean by implicit await or return, does an implicit await mean waiting for a promise to resolve? – tjb Jun 05 '19 at 08:44
  • @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. – T.J. Crowder Jun 05 '19 at 08:49
  • @tjb - I've updated to handle that implicit or explicit thing and add more detail. – T.J. Crowder Jun 05 '19 at 08:50
  • 1
    thanks, I think I'm starting to get this,...but I've thought that alot of times already :) – tjb Jun 05 '19 at 08:53
  • @tjb - LOL, been there! – T.J. Crowder Jun 05 '19 at 08:57