Search code examples
javascriptnode.jsasync-awaites6-promise

What is the meaning of the `async` keyword?


I have been reading up on async/await in Node.js. I have learnt that the await keyword waits for a promise to be resolved, or throws an exception if it was rejected.

I have also learnt that every function that wants to use await needs to be marked async. However, what does it mean for a function to be marked async?

All the resources and blog posts I was able to find seem to explain await in great detail, but ignore the concept of an async function, or briefly gloss over it. For instance, this author puts it like this:

This makes the function return a Promise implicitly.

What does the async keyword really do? What does it mean for a function to implicitly return a Promise? What are the side effects other than being able to use await?


Alright, so from the answers I have received so far it's clear that it simply wraps the function's return value into a Promise, much like Promise.then would. That just leaves a new question though. Why does a function that uses await need to be async and thus return a Promise?


Solution

  • No matter what you actually return from your function, your async function will still return a Promise. If you return a Number, it actually returns a Promise that resolves to the Number your originally returned. This allows you to write synchronous "looking" code.

    Rather than having to write out this:

    function foo(){
        return Promise.resolve("foo");
    }
    

    You can just write this:

    async function foo(){
        return "foo";
    }
    

    and foo() will automagically return a Promise that resolves to "foo".


    In response to you comment:

    Does it behave like Promise.then in the sense that if you already return a Promise, it won't wrap it again?

    await will peel the Promise until it gets to a value:

    async function foo() {
        return Promise.resolve(Promise.resolve(true));
    }
    
    async function bar() {
        return true;
    }
    
    (async function () {
        let tmp;
        tmp = await foo();
        console.log(tmp);
        tmp = await bar();
        console.log(tmp);
        console.log("Done");
    }());
    
    /*
    Prints:
    
    true
    true
    Done
    */
    

    Why is async needed?

    Paraphrasing from @KevinB's comment.

    await, just like yield in a generator, pauses the execution of that context until the Promise it's waiting on is no longer pending. This cannot happen in normal functions.

    If a function is async but does not contain an await, the promise will be resolved immediately, and any callbacks will be ran on the next tick.