Asynchronous Programming in Javascript
Arjun Aravind • 31 August 2020 • 10 min read Alright, I'm pretty excited about this article because it's about a topic I used to have a phobia about. The word 'asynchronous' always sounded extremely complex and advanced and, so, I never really pushed myself to learn it.Thankfully, my company put me into a project related to React Native a few months back and this whole concept of 'async' programming was sorta thrust into my face. However, once I started to get used to it, it didn't seem so scary after that!
- Talking about React Native, check out my article on it here!
So, I thought it'll be nice to introduce this topic in a fun and learnable way to other beginners as well. Right, so, in this article, we will cover what asynchronous programming means and how we can write async programs in Javascript specifically.
What is asynchronous programming?
How much time will it take Batman to finish these tasks?
Let's take a small example here. Let's say that Batman has a busy day ahead of him. He has a variety of tasks to do such as preparing his lunch in the oven (because Alfred took a sick day!), meeting Superman and stopping a crime.
These tasks take 1 hour, 45 mins and 10 mins, respectively. How much time do you think it'll take Batman to finish all his tasks?Let's try out a simple example. First, Batman stops the crime in progress and this takes him 10 minutes. He then proceeds to meet
Now, let's try a more optimised solution. First, Batman stops the crime in progress and this takes him 10 minutes, like before. However, to prepare his lunch, Batman does not need to be in the batcave for the full duration since his lunch will just be sitting in the oven. So, he goes to the batcave, puts his lunch in the oven and this takes him around 5 mins. He then goes to meet Superman which takes 45 mins. He then comes back and waits the 10 remaining minutes for his lunch to get prepared. In total, he has taken 1 hour and 10 minutes.
See how Batman reduced the time he spent by a huge 45 mins? This is because he 'asynchronously' executed his tasks!In computing, the term 'synchronous execution' means executing one task after the other. 'Asynchronous execution' is the exact opposite where the execution of a certain task might be before or after the execution of the previous task.
Let's relate this to programming. In the image below, say you have
function1, function2
and function3
, three functions which take different times to execute. When synchronously executing, a computer would execute function1
first and then execute function2
, and then execute function3
.
When asynchronously executing, a computer will start to execute all three functions at almost the same time and the functions will finish execution according to how much time they take to finish.
So we have seen how async execution can be used to optimise our program.In the same example, if
However, this does not mean that this is always the best method possible!
function2
relies on a value that is computed by function1
, then it is best to stick with a synchronous execution as we do not want function2
to be executed after function1
. This would induce a lot of errors and complicated programming in our program.
One best way to design your application would be to use async execution only when needed. And yes, it is possible to asynchronously execute certain functions and synchronously execute others.
Okay. Wow. Phew! Take a well-needed break. I need one as well. After that, let's move on to how we can use asynchronous execution in Javascript!
Javascript: Promises
The more modern versions of Javascript have given programmers the ability to include asynchronous execution in their programs. We'll be focussing on a very basic overview of these concepts in this article to simplify it for beginners. Let's see how it can be done!
To say it simply, Promises are a container in which we can put the code which must be executed asynchronously. The code inside the Promise must return something.
Imagine it to be something like this. The promise tells the program execution, "Hey, I have some code inside me which is to be executed asynchronously. You keep executing the other functions and I PROMISE to finish executing the code inside me and give you a computed value at some point in the future."
Once the promise is finished executing the code inside it, it tells the program execution, "Yo! I'm done here. Here's the value I computed."
When a promise has not finished executing, we say that it is pending. When it's done, we say it's been fulfilled or resolved.
Check out this example below.
let mypromise = new Promise((resolve) => {
/* Put your asynchronous code here.
We'll leave it empty for now. */
resolve("Resolved successfully")
})
.then((computedValue) => {
console.log(computedValue)
})
Copy this code and paste it in a file named
test.js
and run the command node test.js
(you'll need to install node of course). You should get an output of Resolved successfully
.
Don't worry if this seems like gibberish. Let's break this down together. :-)
First, notice that Promise is created just like an object in Javascript. That is because it is. It's just an object which contains asynchronous code. Second, notice that it takes in a function which has 1 parameter called 'resolve'.
All the asynchronous code we want must be placed inside this function. We can then return something by passing it into the
resolve
function. This resolve
is also what was passed into the parent function.
The
then
function can be called on the Promise object. This is the function called when the Promise has finished executing the asynchronous code inside of it. The value returned in the Promise can be accessed through the computedValue
variable.
Let's look at another example below. This time, with multiple Promises.
/* setTimeout() is a function which executes a function
after a specified amount of time. */
/* This promise will be resolved in 2 seconds. */
let mypromise1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("Resolved 1 successfully")
}, 2000)
})
.then((computedValue) => {
console.log(computedValue)
})
/* This promise will be resolved in 1 second. */
let mypromise2 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("Resolved 2 successfully")
}, 1000)
})
.then((computedValue) => {
console.log(computedValue)
})
Copy this code and paste it in
test.js
and run node test.js
. This time, you should get:-
Resolved 2 successfully
Resolved 1 successfully
Why do you think this happened? Notice that
mypromise1
has a longer time to be resolved than mypromise2
, which is why the result was that mypromise2
got executed first followed by mypromise1
.
There's a lot more to promises which we won't be discussing in this article because I don't want t to cram you with too much information now. Let this all sink in. For further reading on the subject, check out the Mozilla Developer Network, it's really good! I promise (couldn't help it, sorry).
Javascript: Async/Await
Okay, this is the easier one for sure. I'll make this short.
If you want to make a Promise synchronous, you can put
await
in front of it. That's it.
But, you may ask, why the hell would I ever do that? Why are we making an asynchronous object, synchronous? It's like buying a cake and then loading it with pepper on top (don't try this at home, kids).
Sometimes, we might need to make use of a Javascript module which contains asynchronous functions. And you might want to use these in a synchronous execution context. So, that's why. Let's see an example;
async function syncTest() {
let mypromise1 = await new Promise((resolve,reject) => {
setTimeout(() => {
resolve("Resolved 1 successfully")
}, 2000)
})
let mypromise2 = await new Promise((resolve,reject) => {
setTimeout(() => {
resolve("Resolved 2 successfully")
}, 1000)
})
console.log(mypromise1);
console.log(mypromise2);
}
syncTest() /* We call the function here. */
Copy this code and paste it in
test.js
and run node test.js
. This time, you should get:-
Resolved 1 successfully
Resolved 2 successfully
It happened in order this time!
So, basically, we put
await
in front of the Promise and we made it synchronous! But, remember one thing, an await
keyword can only be used inside a function labelled async
, as seen above.
For more information on this, check out the 'Async/Await' page of the Mozilla Developer Network.
--------------
So, I hoped that was informative for you! The objective wasn't to make you an expert but to really introduce the concepts of asynchronous programming and promises in a very un-scary way, hehe. Feel free to get in touch with me about any mistakes, improvements or questions that you might have. Until next time!