Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 219
Galupuf Avatar asked Oct 24 '18 14:10

Galupuf


People also ask

Does async-await always return promise?

Async functions The word “async” before a function means one simple thing: a function always returns a promise. Other values are wrapped in a resolved promise automatically. So, async ensures that the function returns a promise, and wraps non-promises in it.

Does an async function automatically return a promise?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise. Note: Even though the return value of an async function behaves as if it's wrapped in a Promise.resolve , they are not equivalent.

Does await wait for function to finish?

Wait for function to finish using async/await keywords The await keyword allows you to wait until the Promise object is resolved or rejected: await first(); second(); However, the await keyword must be used inside an async function .


2 Answers

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.

like image 146
R.Duteil Avatar answered Oct 29 '22 22:10

R.Duteil


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();
like image 26
Frank Modica Avatar answered Oct 29 '22 21:10

Frank Modica