问题
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