Skip to content

Why does the callback hell works and the async/await doesnt? (in this particular case that i am testing)

I have this two codes (one i use callback hell and other async/await):

function sleep(seconds) {
  const date = Date.now();
  milliseconds = seconds * 1000;
  let currentDate = null;
  do {
    currentDate = Date.now();
  } while (currentDate - date < milliseconds);
}

const callBackHell = () => {
  return Promise.resolve().then((v) => {
    sleep(1);
    console.log("ameno");
    return Promise.resolve().then((v) => {
      sleep(1);
      console.log("dorime");
      return Promise.resolve().then((v) => {
        sleep(1);
        return console.log("latireno");
      });
    });
  });
};

console.log(1);

callBackHell();

console.log(2);

console.log(3);

The callback hell works as i imagined (the string logs appear lastly).

Then i tried to convert the same code but with async/await, like this:

function sleep(seconds) {
  const date = Date.now();
  milliseconds = seconds * 1000;
  let currentDate = null;
  do {
    currentDate = Date.now();
  } while (currentDate - date < milliseconds);
}

const consoleMusical = async (letra) => {
  sleep(1);
  console.log(letra);
};

async function codeBlockerAwait() {
  await consoleMusical("ameno");
  await consoleMusical("dorime");
  await consoleMusical("latiereno");
}

console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);

Now the first await blocks the main thread while the other two keeps showing lastly. What am i doing wrong?

Edit with @Muhammad Saquib Shaikh solution:

function sleep(seconds) {
  const date = Date.now();
  milliseconds = seconds * 1000;
  let currentDate = null;
  do {
    currentDate = Date.now();
  } while (currentDate - date < milliseconds);
}

const consoleMusical = async (letra) => {
  sleep(1);
  console.log(letra);
};

async function codeBlockerAwait() {
  await consoleMusical("ameno");
  await consoleMusical("dorime");
  await consoleMusical("latiereno");
}

(async function () {
  console.log(1);
  await codeBlockerAwait();
  console.log(2);
  console.log(3);
})();

It is not the same output as the first one.

Answer

Now the first await blocks the main thread while the other two keeps showing lastly. What am i doing wrong?

The reason that ameno gets logged up front is that you have that log statement before any awaits. To evaluate the line await consoleMusical("ameno"); it has to execute consoleMusical('ameno'), get its return value, and only then can it await.

The other console.logs happen after the await, so they will get queued up as microtasks to run after the rest of the currently-executing code.

In contrast, all of the console.logs of callBackHell are inside the first promise. So all of them will be queued up as microtasks.


This problem will go away if you use an asynchronous sleep rather than a synchronous one. And as a bonus, you don’t lock up the browser:

function sleep(seconds) {
  return new Promise(resolve => {
    setTimeout(resolve, seconds * 1000);
  });
}

const consoleMusical = async (letra) => {
  await sleep(1);
  console.log(letra);
};

async function codeBlockerAwait() {
  await consoleMusical("ameno");
  await consoleMusical("dorime");
  await consoleMusical("latiereno");
}

console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);

If you absolutely must have a synchronous sleep, while still wanting to keep the same order of operations, you’ll need to add an additional await.

function sleep(seconds) {
  const date = Date.now();
  milliseconds = seconds * 1000;
  let currentDate = null;
  do {
    currentDate = Date.now();
  } while (currentDate - date < milliseconds);
}

const consoleMusical = async (letra) => {
  sleep(1);
  console.log(letra);
};

async function codeBlockerAwait() {
  await undefined; // <--------- added
  await consoleMusical("ameno");
  await consoleMusical("dorime");
  await consoleMusical("latiereno");
}


console.log(1);
codeBlockerAwait();
console.log(2);
console.log(3);