What is the meaning of the `async` keyword?

安稳与你 提交于 2021-02-17 07:18:34

问题


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?

EDIT:

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?


回答1:


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.




回答2:


What does async do?

async is syntactic sugar for making your method chain Promise objects. Take the following method for example:

async function myFunction(a)
{
    if (a == 10) 
    {
        await otherFunction();
    }

    return 10;
}

The JavaScript runtime you use might make more optimized code, but in its simplest it will be something along the lines:

function myFunction(a) 
{
    if (a === 10) 
    {
        return otherFunction()
          .then(() => myFunction_continuation());
    }
    else 
    {
        return myFunction_continuation();
    }

    function myFunction_continuation() 
    {
        return Promise.resolve(10);
    }
}

For documentation on the Promise type I recommend checking out the Mozilla Developer Network page about the Promise type .

Why do you need to mark it async? Why not just use await?

Because your method needs to be split up into multiple "parts" for it to be able to have code execute after the method being awaited on. The example above has a single continuation, but there could be multiple.

The designers of JavaScript want to make it visible to the developer that the runtime is doing this "magic". But maybe the most important reason is that they don't want to break existing code using await as a variable name. They do this by making await a "contextual keyword". A "contextual keyword" is only a keyword in specific scenarios, in this case: when used inside a method marked as async:

function ABC() 
{
    var await = 10;
}

The above compiles. But if I add the async keyword to the function declaration it no longer does and throws an Uncaught SyntaxError: Unexpected reserved word.




回答3:


Asynchronous Task Running

The Basic idea is to use a function marked with async instead of a generator and use await instead of yield when calling a function, such as:

(async function() {
    let contents = await readFile('config.json');
    doSomethingWith(contents);
    console.log('Done');
});

The Async Keyword before function indicates that the function is meant to run in an asynchronous manner. The await keyword signals that the function call to readFile('config.json') should return a promise, and if it doesn't, the response should be wrapped in a promise.

The end result is that you can write asynchronous code as if it were synchronous without overhead of managing an iterator-based state machine.

  • Understanding ECMACSCRIPT 6 by Nicholas c. Zakas


来源:https://stackoverflow.com/questions/49636379/what-is-the-meaning-of-the-async-keyword

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!