Galupuf
Galupuf

Reputation: 2947

Async function returning before await is complete

I have two questions from the following example:

Why is does x log before y? Why is x a Promise?

I'm expecting bar to wait for foo to resolve with the value 'Hello' before it logs and then returns it.

let foo = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Hello');
        }, 2000);
    })
}

let bar = async () => {
    let y = await foo();
    console.log(y);
    return y;
}

let x = bar();

console.log(x);

What I'm expecting to see is

'Hello' // console.log(y)
'Hello' // console.log(x)

What I'm getting is

 Promise {<pending>}  // console.log(x)
 'Hello'              // console.log(y)

Shouldn't bar wait for foo to resolve before returning y?

Any help would be much appreciated!

Upvotes: 12

Views: 12046

Answers (3)

R.Duteil
R.Duteil

Reputation: 1217

Here is the documentation about async function: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

And Promise object: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

It is stated that an async function returns a Promise object which is in a pending state until it is resolved.


Now let's look at your code:

You assign to x the return value of bar(), which is a Promise, since there is no await keyword to stop the execution (And you can not add one, because you are outside of an async function) this promise is logged as pending because the async function bar() has not yet returned.

Meanwhile, in the async function bar() you assign to y the return value of the async function foo() which is also a Promise, but this time you make it await for the result. After 2 seconds of waiting time, the promise is fulfiled and y is logged with the parameter of the resolve() method, which is Hello.

Thus the behaviour you witness is the expected one.

Upvotes: 8

Frank Modica
Frank Modica

Reputation: 10516

You need to await the function:

let example = async () => {
    let foo = () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('Hello');
            }, 2000);
        })
    }

    let bar = async () => {
        let y = await foo();
        console.log(y);
        return y;
    }

    let x = await bar();

    console.log(x);
}

example();

Upvotes: 7

user10516706
user10516706

Reputation:

You should use an await before calling bar() but, actually, you can use await just when you wrapped it by a async function like below:

async function Func() {

  let foo = () => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Hello');
      }, 2000);
    })
  }

  let bar = async () => {
    let y = await foo();
    console.log(y);
    return y;
  }

  let x = await bar();

  console.log(x);

}

When you execute the Func(); your expectation will fire.

Upvotes: 0

Related Questions