Async
& Await
is a part of ECMAScript 6. It is another way of handling promises in a more sophisticated way. It makes
asynchronous code cleaner, easier to write and to read, and also make it look like synchronous code. The async
is used with
a function to makes it into an asynchronous function. The await
keyword is used to invoke an asynchronous function synchronously. The
await
keyword holds the JS engine execution until promise is resolved.
function getRandomValue(){ return new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve("I am from async function"); }, 3000) }) } var res = getRandomValue(); res.then(val => console.log(val)); console.log('value printed'); //Output: value printed //Output: I am from async function
In the above example you can see that, console.log('value printed');
is printed prior to res.then(val => console.log(val));
,
and this is becasue getRandomValue
is returning a promise. Javascript engine executes the code synchronously and do not wait for asynchronous code
to be resolved. Hence, It move to next line and print value printed
before. Read about
Javascript- Event loop to understand "how
JavaScript engine handle asynchronous code?".
What if we do not want the execution to bypass and jump to the next line. What if the value returned from the async function is used in the next line. Let's make some changes in the above code to make it behave synchronously.
async function getRandomValue(){ return new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve("I am from async function"); }, 3000) }) } var res = await getRandomValue(); console.log('res >>> ', res); //output: I am from async function
In the above example, when JS engine encounters await getRandomValue()
it holds the execution and wait until
await getRandomValue
is resolved and value is returned.
Let's consider a scenario where you get some data from an async function and based on the returned value you are invoking another function.
function getSandwich(){ getBreaed().then(bread => { applyCatchup(bread).then(breadWithCatchup => { stuffVegetable(breadWithCatchup).then(sandwich => { console.log("satndwitch is ready "+ sandwich); }) }) }) }
In the above example, you can see that- to make a sandwich we need to do dependent calls. We can apply tomato catchup only if double bread is available. we can stuff vegetables only if we have double bread with catchup. That's why there is nested asynchronous calls.
Suppose we have lot more dependent async calls, then there will be too many nested .then()
calls. It will make the code cluttered and
not easy to read. Though, It is perfectly right to do this way. It does not have any performance issue.
However, We can use async
and await
to make it synchronised. Code will be much cleaner, shorter and readable.
When should we use async and await?
In the above example, stuffVegetable()
can be executed only after applyCatchup
execution is over. And applyCatchup
can be executed only after getBreaed
execution is over.
stuffVegetable
funtcion can be called with breadWithCatchup
parameter and applyCatchup
function can be
called with bread
parameter.
we know that, whenever JS engine encounter await
, it waits for that async function to yield the result. The above example of making sandwich is
perfect scenario to use Async
& Await
.
var bread = await getBreaed(); var breadWithCatchup = await applyCatchup(bread); var sandwich = await stuffVegetable(breadWithCatchup);
You can see, 7 lines of code is cleanly written in 3 lines. It is much shorter, cleaner and easy to read and understand.
We should use async & await only when we want the result immediately. Maybe the result is being returned from the function or getting used in the next line.
When should we not use async and await?
The async
and await
makes execution synchronous which is its draback also. next async call will happen only
if previous one is over.
Let's take a real-life example:- Suppose there is a queue of people. People in the queue are waiting for their turn to resolve their query with the helpdesk. Few of them have lots of queries which might take 3 to 5 minutes. Few of them have a smaller query which can be resolved in just 1 minute or less than that. If we try to replicate this in a programming language, it is not a wise idea to make the person wait for a longer period if his/her query can be resolved in 1 minutes. Instead, we can parallelly give them a chance to go to a helpdesk and resolve their query. In this way, they have to wait only for their query to be resolved.
//Bad way var solutionPerson1 = await resolvePerson1Query(); //takes 2 min var solutionPerson2 = await resolvePerson2Query(); //takes 3 min var solutionPerson3 = await resolvePerson3Query(); //takes 3 min var solutionPerson4 = await resolvePerson4Query(); //takes 1 min
We are able to execute the above code synchronously. But, is it a good idea to do that?
From above, we calculate that Person4 has to wait for 8 minutes before his turn come. It is a very bad idea. In terms of page performance
it is huge performance issue.
//Good way var solutionPerson1Promise = resolvePerson1Query(); var solutionPerson2Promise = resolvePerson2Query(); var solutionPerson3Promise = resolvePerson3Query(); var solutionPerson4Promise = resolvePerson4Query(); solutionPerson1Promise.then(res => { console.log(res) }); solutionPerson2Promise.then(res => { console.log(res) }); solutionPerson3Promise.then(res => { console.log(res) }); solutionPerson4Promise.then(res => { console.log(res) }); //Output > solution Person 4 solution Person 1 solution Person 2 solution Person 3
From the above example, we can see that Person 4
query is resolved first and this is what we expect. We dont want Person 4
to
wait for 8 minutes before he get a chance to resolve the query with helpdesk.
If you have scenarios like this, you should definitely avoid usig async, await
. It unnecessarily holds the execution which you would not want.
0 Comments