Why Is Async Required To Call Await Inside A Javascript Function Body?
Solution 1:
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:
functionfoo() { if (Math.random() < 0.5) { return'return'; } else { throw'throw'; } } asyncfunctionbar() { if (Math.random() < 0.5) { return'return'; } else { throw'throw'; } }
async
performs the following transformation offunction bar()
:functionbar() { returnnewPromise((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:
functionbar() { returnnewPromise((resolve) => { if (Math.random() < 0.5) { returnresolve('return'); } else { throw'throw'; } }); }
Solution 2:
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 methodsasyncfunctionfetchMovies() {
const response = awaitfetch('/movies');
console.log(response);
}
awaitfetchMovies();
// Closing connection to avoid attacks and maintain concurrencyawait 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.
Solution 3:
I think it's to make it clear that the function contains asynchronous code. Let's use another example that does return something:
asyncfunctioncanUseGeolocation() {
const result = await navigator.permissions.query({name: 'geolocation'});
return result.state;
}
The async
keyword tells the javascript engine that the function should return a promise, and any return statements in the function should resolve that promise. What happens if we modify it to cache the values so we don't always call the await?
functioncanUseGeolocation() {
if (cachedPermissionState) return cachedPermissionState;
const result = await navigator.permissions.query({name: 'geolocation'});
cachedPermissionState = result.state;
return result.state;
}
How should javascript know that the function should return a promise? Because it contains an await
? What if you later change the function so that the cachedPermissionState
is set elsewhere and this function only returns that value so you remove the await
? Should that first return statement return a promise or return the value? That would now change the whole way the function is executed and what is returned by return cachedPermissionState;
. By using async
, we can know that it really returns a promise that the return statement resolves without scanning the function for await
statements to determine if it should be treated as async
or not.
Solution 4:
There are two questions being asked here. Why do you need the async keyword to indicate an async context, and why do you need async context to use await?
If we didn't use the async keyword to indicate an async context, then we would have backwards compatibility issues. Before the async/await update, "await" was a valid variable name. So to make it a reserved word, we need to introduce a new context, the async function context.
The second question is, why do we want this in the first place? Why do we want to differentiate async functions from traditional synchronous code? As the name implies, async functions do not execute all their code at once. When a function "awaits", it effectively stops execution, and the remainder of the code becomes an event handler for the thing being awaited. This allows other code to run.
Browser javascript implementations are single-threaded. Only one thing can be performed at a time, but the event queue allows functions to take turns. Consider what would happen if you could await from a synchronous function. The synchronous code, by definition, does not give up control. Therefore, the async function it's waiting for will never get a chance to swap in to your single execution thread, and you will be waiting forever. So, you can only await an async function if you are already in an async context.
Post a Comment for "Why Is Async Required To Call Await Inside A Javascript Function Body?"