skip to Main Content

the following code results into the expected output

function toppings_choice() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(console.log("which topping would you love?"));
      reject("not working");
    }, 3000);
  });
}

async function kitchen() {
  console.log("A");
  console.log("B");
  console.log("C");

  await toppings_choice();

  console.log("D");
  console.log("E");
}

kitchen();
/* Stackoverflow: show only console */
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

output:
A
B
C
which topping would you love?
D
E

but for some reason await in the following syntax does not work

async function toppingChoice() {
  setTimeout(() => {
    if (true) {
      return console.log("which topping would you love?");
    } else {
      throw "not working";
    }
  }, 3000);
}

async function kitchenTwo() {
  console.log("A");
  console.log("B");
  console.log("C");

  await toppingChoice();

  console.log("D");
  console.log("E");
}

kitchenTwo();
/* Stackoverflow: show only console */
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

output:
A
B
C
D
E
which topping would you love?

both functions return a promise, so why is the await keyword working in the first code and indeed stopped the code until the promise was resolved but did not work in the second code?

I need to know if I could use the syntactic sugar of sync/await without having to use the promise constructor

2

Answers


  1. both functions return a promise

    Not really, at least it’s not the case for your toppingChoice.

    The first one

    function toppings_choice() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(console.log("which topping would you love?"));
          reject("not working");
        }, 3000);
      });
    }
    

    returns a promise which is fulfilled only after the timeout calls its callback.

    The second

    async function toppingChoice() {
      setTimeout(() => {
        if (true) {
          return console.log("which topping would you love?");
        } else {
          throw "not working";
        }
      }, 3000);
    }
    

    doesn’t return anything in explicit way (no return) which makes it implicitely return a fulfilled promise with undefined value. When this promise is awaited, it doesn’t even make the execution wait for anything. It’s only 3000,s later when the timeout callback is called.

    Note that adding return here

    async function toppingChoice() {
      return setTimeout(() => { ...
    

    won’t help much as the result of setTimeout is not meant to be awaited (it’s the timer id, a number).

    I need to know if I could use the syntactic sugar of sync/await without having to use the promise constructor

    You can, assuming you run your code in node. Node has two versions of the setTimeout, the old one, compatible with the browser API and an new one that returns a promise.

    Login or Signup to reply.
  2. The problem in your 2nd approach is, that you return a Promise (since all function with the async keyword do that), but that promise immediately resolves (or better: a completed Promise is returned), therefore the program continues to run and exits before the callback specified for setTimeout() is scheduled to run on the event loop.

    If you were to wait longer than 3 seconds before exiting the program you could observe that the callback actually gets invoked:

    async function toppingChoice() {
      setTimeout(() => {
        if (true) {
          return console.log("which topping would you love?");
        } else {
          throw "not working";
        }
      }, 3000);
    }
    
    async function kitchenTwo() {
      console.log("A");
      console.log("B");
      console.log("C");
    
      await toppingChoice();
      console.log("D");
      console.log("E");
    
      // wait before exiting the program so the callback set by setTimeout() gets to run
      await waitForMs(5000);
    }
    
    kitchenTwo();
    
    function waitForMs(milliseconds){
      return new Promise(res => setTimeout(() => res(), milliseconds));
    }
    /* Stackoverflow: show only console */
    .as-console-wrapper {
      max-height: 100% !important;
      top: 0;
    }

    To really understand how this works you need an understanding of the event loop in JavaScript and you need to understand that behind a Promise is actually a state machine but all of that is too much to go into detail here. Please have a look at the referenced resources.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search