Why is async required to call await inside a JavaScript function body?
I assume your exact question is this: "Handling return values (null or something) depends on the consumer who called the function. They "should" supposedly get it even if another asynchronous function is called in-between. So why does it matter to wait before further other asynchronous calls?"
You see, such fetch()
calls are done in Databases within the duration of "initiating" and "closing" the connection. Almost every method used is asynchronous in this case. So while you're executing fetchMovies();
The thread might move further and execute connection.close();
before the fetching is resolved and returned.
The exact scenarios are like this:
await client.connect(); //connection establishment
// Your purposeful methods
async function fetchMovies() {
const response = await fetch('/movies');
console.log(response);
}
await fetchMovies();
// Closing connection to avoid attacks and maintain concurrency
await client.close();
If any method, in this case, is called in an asynchronous manner, the whole session of a Database connection is wasted and our function would return undefined
or throw an error "Cannot use a session that has ended"
So we need to "wait" for the "Pending" Promises to reach a "Fulfilled" or "Rejected" state before executing further calls.
You can refer more to this article: Using Promises, async / await with MongoDB just for the sake of understanding.
There are three reasons the async
keyword exists:
In ECMAScript language versions prior to 2015,
await
was not a keyword. Marking a functionasync
provides a syntactic "bailout" to indicate a breaking change in the language grammar within the body of the function.This is the most important reason. Without the
async
keyword, all programs written in ECMAScript 5 or older would no longer work if they used theawait
keyword as a variable (in fact this was done intentionally in some cases as a polyfill beforeasync
/await
was standardized), since that would cause a breaking change without the addition ofasync
to the specification. Because of this,async
is syntactically necessary to avoid breaking changes to the language.It provides a convenient marker for parsers, avoiding an infinite look-ahead in order to determine whether or not a function is asynchronous.
This makes parsing more efficient, which is appealing for both ECMAScript implementers and developers, though this reason alone does not make
async
strictly necessary to the syntax.async
also performs its own transformation on the function, which is done regardless of whether or not theawait
keyword is present in the body.Consider the following two functions:
function foo() { if (Math.random() < 0.5) { return 'return'; } else { throw 'throw'; } } async function bar() { if (Math.random() < 0.5) { return 'return'; } else { throw 'throw'; } }
async
performs the following transformation offunction bar()
:function bar() { return new Promise((resolve, reject) => { try { resolve((/*async function bar*/() => { if (Math.random() < 0.5) { return 'return'; } else { throw 'throw'; } })()); } catch (reason) { reject(reason); } }); }
Those familiar with promises will recognize that we can simplify the above since the Promise constructor executor function will implicitly reject if it throws an error synchronously:
function bar() { return new Promise((resolve) => { if (Math.random() < 0.5) { return resolve('return'); } else { throw 'throw'; } }); }