Master Asynchronous Programming
Hello HaWkers! Jeff Bruchado here.
This is another article in our series that will cover our journey to Learn Programming from Scratch.
Well, without further ado, let's get started!
Today, we're going to talk about Asynchronous Programming in JavaScript:
Let's think of a scenario:
You're creating an application and there's a part that needs to fetch weather information, like weather forecasts, temperature, and different types of data, directly from an API (an external data source).
Then you ask me: "So what? What's the difference?"
The difference, my friend, is that this information doesn't arrive instantly, like an order at a drive-thru.
It can take a while, because it depends on an internet connection, the API server... and a few other things.
Asynchronous Programming comes into play to handle these waits, without leaving your app stuck, waiting for the response to arrive.
It's like ordering a pizza and being able to watch your favorite series while waiting for delivery, you know?
Why is this important?
With this, the program doesn't freeze: Without asynchrony, your app would freeze, waiting for the API response. With it, the app keeps running smoothly while waiting.
Improves user experience: Nobody likes an app that freezes or takes too long to respond. Asynchronous Programming keeps things flowing.
Efficiency: You can do multiple things at once. While one piece of information is being fetched, other parts of your app can continue working.
In JavaScript, the magic happens with tools like Promises and Async/Await.
They're like contracts that something will happen, but not right now.
For example:
fetch('weather-api-url')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.log(error));In this code, the fetch function fetches the data, and meanwhile, the rest of your app doesn't stay stuck waiting. When the data arrives, the .then() is executed.
So that's it: Asynchronous Programming is fundamental because it keeps your app agile, efficient, and much more pleasant to use.
Without it, it would be like standing in a huge line waiting for something that could be done while you do other things.
Who wants that, right?
Understanding Asynchronous Programming
Asynchronous Programming is a programming technique that allows code to execute in a non-blocking way.
This means that while a task is being performed, the code can continue to execute without waiting for the task to complete.
This is useful when the task may take a long time to complete, like making an API call.
In JavaScript, asynchronous programming is generally implemented with callbacks or promises.
Callbacks
They're functions that are passed as arguments to other functions and are called when the asynchronous operation is complete.
For example:
function getData(callback) {
// makes a request and gets the data
let data = 'some data';
callback(data);
}
getData(function (data) {
console.log(data); // some data
});Callbacks are a key piece in the Asynchronous Programming puzzle, and understanding how they work will save you many headaches.
So, what are these Callbacks?
Imagine you're organizing a party and ask your partner to bring the drinks. You say: "Call me when you arrive, and I'll come down to help you carry everything up".
This "call me when you arrive" is basically a callback in real life.
In the programming world, a callback is a function that is passed as an argument to another function and is executed after a task is completed.
Why are they important?
Asynchronous flow control: In JavaScript, often you're dealing with operations that take time to happen, like fetching data from an API. Callbacks help you say: "Hey, after you finish this, do this here".
Code continuation: They allow you to continue with other operations while waiting for something to complete. This way, your program doesn't get stuck waiting.
Result handling: When you receive the result of an asynchronous operation, the callback handles that result. In other words, you can process and use that data.
For example:
function fetchData(url, callback) {
fetch(url)
.then(response => response.json())
.then(data => callback(null, data))
.catch(error => callback(error, null));
}
fetchData('api-url', function (error, data) {
if (error) {
console.log('Oops, error:', error);
} else {
console.log('Here is the data:', data);
}
});In this code, fetchData is a function that fetches data from an API. When the fetch is complete (whether successfully or with an error), the callback is called with the results.
But be careful: Callbacks can lead to the dreaded "Callback Hell" or "Pyramid of Doom", which is when you have a bunch of nested callbacks and your code becomes a maze.
That's why it's important to use them wisely and consider alternatives like Promises and Async/Await to keep code clean and readable.
So that's it, callbacks are like the messengers of the asynchronous world, carrying information from one point to another and ensuring things happen in the right order. Cool, right?!
Promises
Promises are a more modern feature for dealing with asynchronous programming.
They're objects that represent the eventual completion or failure of an asynchronous operation.
Instead of passing a callback function as an argument, you can use the Promise's then method to specify what should be done when the Promise is resolved or rejected.
For example:
function getData() {
return new Promise(function (resolve, reject) {
// makes a request and gets the data
let data = 'some data';
resolve(data);
});
}
getData()
.then(function (data) {
console.log(data); // some data
})
.catch(function (error) {
console.error(error);
});The async operator and the await keyword are an even more convenient way to deal with asynchronous programming.
They allow you to write synchronous-looking code, but that is actually asynchronous.
For example:
async function getData() {
// makes a request and gets the data
let data = await someAsyncFunction();
console.log(data);
}
getData();Callback Hell
Callback Hell, as I mentioned earlier, is a term used to refer to code that consists of many layers of nested callback functions, which can be difficult to read and maintain.
This is common when using callbacks to handle asynchronous programming and can be avoided using techniques like Promises and async/await.
Here's an example of how code can get complicated with excessive use of callbacks:
getUserData(function (user) {
getComments(user.id, function (comments) {
getLikes(user.id, function (likes) {
getFollowers(user.id, function (followers) {
console.log(
`${user.name} has ${comments.length} comments, ${likes.length} likes, and ${followers.length} followers.`
);
});
});
});
});Using Promises, this same code can be written as follows:
getUserData()
.then(function (user) {
return getComments(user.id);
})
.then(function (comments) {
return getLikes(user.id);
})
.then(function (likes) {
return getFollowers(user.id);
})
.then(function (followers) {
console.log(
`${user.name} has ${comments.length} comments, ${likes.length} likes, and ${followers.length} followers.`
);
})
.catch(function (error) {
console.error(error);
});And using async/await, the code can be written as follows:
async function getStats() {
try {
let user = await getUserData();
let comments = await getComments(user.id);
let likes = await getLikes(user.id);
let followers = await getFollowers(user.id);
console.log(
`${user.name} has ${comments.length} comments, ${likes.length} likes, and ${followers.length} followers.`
);
} catch (error) {
console.error(error);
}
}
getStats();As you can see, using Promises or async/await, the code is more readable and easier to maintain than using multiple nested callbacks.
Conclusion
In summary, asynchronous programming is a technique that allows code to continue executing while waiting for the return of an asynchronous function call.
This is useful when the operation may take a long time to complete, like when making a request to an API.
In JavaScript, there are several ways to handle asynchronous programming, such as callbacks, Promises, and async/await.
Each of these approaches has its own advantages and disadvantages and it's important to understand when to use each one.
I personally use the following rule to decide whether to use Promises or async/await:
When a request has data that depends on data from another request, async/await is most recommended, because this way you ensure that the second request will only be executed when you've received the response from the first.
But as you can see, this makes your program slow. Because you have to wait for the first request to only then execute the next one.
However, when you're going to execute two requests in sequence, and one request doesn't depend on the response from the other, then in this case it's more recommended to use Promises, because this way you can execute both requests at the same time, making your code much faster.
Additionally, it's important to be careful with "Callback Hell", or excessive nesting of callbacks, to keep code readable and easy to maintain.
Well HaWker, we've reached the end of another article.
As always, if you have any questions or want to explore any point further, just reply with your question to this email.
And remember, I'm here to help you improve 1% with each new article!
If you made it this far, as usual, please reply to this email with "I managed to understand Asynchronous Programming in JavaScript".
This way I'll know that this article series is being useful for you, and that you're following along and taking advantage.
As you already know! Only a true HaWker makes it to the end.
Congratulations!
I'm happy to have you here.
See you soon.
Let's go! 🦅
- Jeff Bruchado
When you feel the time is right, there are 2 ways I can help you:
01) Learning JavaScript from Scratch: Become a valuable programmer and learn to program using JavaScript, with organized and condensed content focused on what really matters for you to learn. The content has all the articles I've been sharing weekly with you, and also has practical exercises, with answers for you to learn the theory and immediately start getting hands-on.
02) Consulting: Join my mentorship and have classes directly with me. If you're interested in this, reply to this email with "I'm interested in the mentorship."
Congratulations on making it this far, HaWker! 🎉
Now that you've learned about asynchronous programming in JavaScript, how about testing your knowledge? Take the quiz below and see how much you absorbed from our article.
It's a great way to reinforce learning and prepare for the next steps in your programming journey.
Good luck and have fun!

