Search code examples
javascriptasync-awaites6-promise

JavaScript Async/Await logic behaving as synchronous


If I understood correctly, a function declared with the keyword async should return a promise. In the case of the async3 function, we have 1 billion iterations, which makes the return value take a little longer. Analyzing the code below, what I expected to happen is that, by invoking the sync1 and sync2 function, immediately log on the console and, later, the async3 function log would come. However, what I've noticed is that the sync1 and sync2 functions only log after async3 has ended. Wouldn't the async3 function be supposed to be running on another thread or outside the event loop without blocking the execution of the other functions invoked on the runtime?

function sync1() {
  console.log(1);
}

function sync2() {
  console.log(2);
}

async function async3() {
  let iteration = 0;
  let number = 0;
  while (iteration <= 1000000000) {
    number = iteration;
    iteration++;
  }
  return number;
}

sync1();
sync2();
async3().then((val) => console.log(val));

Can you clarify why it behaves like that. What am I missing?

What I expected:

sync1(); // console logged immediately
sync2(); // console logged immediately
async3().then((val) => console.log(val)); // console logged moments later

What's currently happening:


     sync1(); // console logged after async3 is done 
     sync2(); // console logged after async3 is done
     async3().then((val) => console.log(val)); // console logged after async3 is done


Solution

  • Remember that JavaScript is fundamentally single-threaded.

    Although async3 is async, its operations are entirely synchronous, and CPU intensive. The output will only be (visually) printed to the console once the browser has a bit of idle time, but the following block:

      while (iteration <= 1000000000) {
        number = iteration;
        iteration++;
      }
    

    leaves the browser no idle time until the above calculations are finished.

    For sync1 and sync2 to log immediately, one solution would be to have async3 pause every 100,000 iterations (or something), and await a setTimeout, thereby giving the browser a chance to do stuff like display stuff to the console, handle other event listeners, render changes, and so on.

    Another solution would be to do the computation-heavy async3 function in a worker instead, which is on a separate thread, which won't block the browser's main thread.