Why does using await
need its outer function to be declared async
?
For example, why does this mongoose statement need the function it's in to return a promise?
async function middleware(hostname, done) {
try {
let team = await Teams.findOne({ hostnames: hostname.toLowerCase() }).exec();
done(null, team);
} catch (err) { done(err); }
}
I see the runtime/transpiler resolving the Teams promise to it's value and async signaling it "throws" rejected promises.
But try/catch "catches" those rejected promises, so why are async and await so tightly coupled?
Why does using await
need its outer function to be declared async
?
For example, why does this mongoose statement need the function it's in to return a promise?
async function middleware(hostname, done) {
try {
let team = await Teams.findOne({ hostnames: hostname.toLowerCase() }).exec();
done(null, team);
} catch (err) { done(err); }
}
I see the runtime/transpiler resolving the Teams promise to it's value and async signaling it "throws" rejected promises.
But try/catch "catches" those rejected promises, so why are async and await so tightly coupled?
Share Improve this question edited Sep 5, 2019 at 19:47 temporary_user_name 37.1k48 gold badges160 silver badges243 bronze badges asked May 25, 2017 at 15:16 Michael ColeMichael Cole 16.2k7 gold badges89 silver badges98 bronze badges 5 |3 Answers
Reset to default 10I'm not privy to the JavaScript language design discussions, but I assume it's for the same reasons that the C# language requires async
(also see my blog).
Namely:
- Backwards compatibility. If
await
was suddenly a new keyword everywhere, then any existing code usingawait
as a variable name would break. Sinceawait
is a contextual keyword (activated byasync
), only code that intends to useawait
as a keyword will haveawait
be a keyword. - Easier to parse.
async
makes asynchronous code easier to parse for transpilers, browsers, tools, and humans.
Copied from https://stackoverflow.com/a/41744179/1483977 by @phaux:
These answers all give valid arguments for why the async keyword is a good thing, but none of them actually mentions the real reason why it had to be added to the spec.
The reason is that this was a valid JS pre-ES7
function await(x) { return 'awaiting ' + x } function foo() { return(await(42)) }
According to your logic, would
foo()
returnPromise{42}
or"awaiting 42"
? (returning a Promise would break backward compatibility)So the answer is:
await
is a regular identifier and it's only treated as a keyword inside async functions, so they have to be marked in some way.Fun fact: the original spec proposed more lightweight
function^ foo() {}
for async syntax.
Because using await
inside middleware
function means the middleware
function can't return a result immediately (it must wait until await
is settled) and middleware
function callers must wait until the promise (returned from middleware
function) is settled.
async
keyword? – Bergi Commented May 25, 2017 at 20:15