0

I don't understand why following execution output is 1 3 4 2 6 5;

Promise.resolve().then(() => console.log(2));

(async() => console.log(await 6))();

console.log(1);

(async() => await console.log(3))();

Promise.resolve().then(() => console.log(5));

console.log(4);
Andy
  • 61,948
  • 13
  • 68
  • 95
trigold
  • 51
  • 7

3 Answers3

1

Here's how your code executes:

  1. Promise.resolve() creates a resolved promise which puts () => console.log(2) in the micro-task queue

    queue: [ 
       () => console.log(2)
    ]
    
  2. The IIFE executes in which you have await 6. Awaiting 6 is similar to wrapping it in Promise.resolve(6) and then awaiting it: await Promise.resolve(6).

    When the operand of await is not a promise, await creates a native promise and uses the operand's value to resolve that promise

    queue: [ 
       resolve(6),
       () => console.log(2)
    ]
    
  3. 1 is logged on the console

    queue: [ 
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1
    
  4. Second IIFE executes where you have await console.log(3). This is like await undefined because console.log(3) will execute, 3 will be logged on the console and the return value of console.log, i.e. undefined will be awaited.

    In short, you are awaiting undefined.

    queue: [ 
       resolve(undefined),
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1 3
    
  5. Promise.resolve() creates a resolved promise which puts () => console.log(5) in the micro-task queue

    queue: [ 
       () => console.log(5),
       resolve(undefined),
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1 3
    
  6. 4 is logged on the console

    queue: [ 
       () => console.log(5),
       resolve(undefined),
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1 3 4
    
  7. Script execution end

  8. Event loop will now begin processing the micro-task queue

  9. 2 will be logged on the console because it was queued first

    queue: [ 
       () => console.log(5),
       resolve(undefined),
       resolve(6)
    ]
    
    console output: 1 3 4 2
    
  10. await 6 resolves with the value 6 which is then passed to console.log. As a result 6 is logged on the console

    queue: [ 
       () => console.log(5),
       resolve(undefined)
    ]
    
    console output: 1 3 4 2 6
    
  11. Promise created as a result of await console.log(3) resolves with the value of undefined

    queue: [ 
       () => console.log(5)
    ]
    
    console output: 1 3 4 2 6
    
  12. 5 is logged on the console

    queue: [ ]
    
    console output: 1 3 4 2 6 5
    
  13. Done.


Note: Your code shouldn't rely on the timing and order in which different unrelated promises are resolved.

Yousaf
  • 27,861
  • 6
  • 44
  • 69
0

There are two sequences here: 1 3 4 and 2 6 5. The first is produced on the first tick (before any promises have resolved, and the second on the second tick (after promise resolution).

(async() => await console.log(3))(); writes 3 to the log before the await, so the 3 appears before any promises resolve, and between 1 and 4 because of the order of the statements. (Note that the await in this line resolves to undefined, because console.log doesn't return anything).

For the sequence 2 6 5, all of the console logs come after a promise resolves (or, equivalently, an await statement), and they're in natural order otherwise.

phhu
  • 1,462
  • 13
  • 33
0

1 is printed first because of order of execution. 3 is printed as code is executed because console.log() is not an asynchronous operation. Does not matter if you put await in front of it. 4 is again printed because of order of execution.

Now, rest of the order of execution is due to asynchronous operations. The 3 statements are printed in an asynchronous manner after the above 3 statements are executed.

Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39