Asynchronous JavaScript with async/await
- 03 Apr, 2022

What is asynchronous JavaScript?
JavaScript is a single-threaded language. This means that it can only execute one task at a time. This is not a problem when you are doing simple things like adding two numbers together, but it becomes one when you are doing more complex things like fetching data from a server or processing complex algorithms that require intensive computations.
When you are doing these kinds of things, you don’t want to block the main thread. You want to be able to do other things while you are waiting for the data to be fetched or the file to be read. This is where asynchronous JavaScript comes in.
How to write asynchronous JavaScript?
There are two ways to write asynchronous JavaScript: callbacks and promises.
In the old days, callbacks were the way to go, but nowadays promises are the preferred way.
Moreover, the recent addition of the async/await
syntax in JavaScript has made writing asynchronous code even more
concise and readable
Callbacks
Callbacks are functions that are passed as arguments to other functions. That’s it. That’s all there is to it.
function doSomethingAsync(onSuccessCallback) {
// do something that takes a lot of time
onSuccessCallback(data);
}
doSomethingAsync((result) => {
console.log("hello there ", result);
});
It looks simple enough, however, callbacks can become cumbersome and hard to manage when you have multiple asynchronous operations happening in parallel, especially when you need to perform a series of operations that depend on the completion of previous operations.
asyncOperation1(function (error, result1) {
if (error) {
// Handle error
} else {
asyncOperation2(result1, function (error, result2) {
if (error) {
// Handle error
} else {
asyncOperation3(result2, function (error, result3) {
if (error) {
// Handle error
} else {
asyncOperation4(result3, function (error, result4) {
if (error) {
// Handle error
} else {
// Do something with result4
}
});
}
});
}
});
}
});
That’s a lot of nesting. It’s hard to read and understand what’s going on. It’s also hard to debug when something goes wrong. And it’s even harder to add new operations or change the order of operations. That’s why it was called “callback hell”. And that’s why promises were invented, to save us from this madness.
Promises
Promises are objects that represent the eventual completion (or failure) of an asynchronous operation, and its resulting value. Or in other words: it’s an object that represents a value that may not be available yet but will be resolved eventually.
A Promise can be in one of three states: pending, fulfilled, or rejected. When a Promise is pending, it means that the asynchronous operation is still in progress. When the operation is complete and is successful, the Promise is fulfilled, and the success callback is called. If the operation fails, the Promise is rejected, and the error callback is called.
Let’s take a look at an example:
function getData() {
return new Promise(function (resolve, reject) {
// Perform the asynchronous operation here, such as making an HTTP request
// When the operation is complete, call the resolve or reject function
if (/* operation was successful */) {
resolve(data);
} else {
reject(error);
}
});
}
// Call the getData function and attach a set of callbacks to the Promise object
getData().then(function (data) {
// Handle the successful completion of the asynchronous operation here
}).catch(function (error) {
// Handle the error case here
});
The code above calls the getData
function and attaches a set of callbacks to the Promise object. The then
method is
used
to handle the successful completion of the asynchronous operation, and the catch
method is used to handle the error
case.
You could also use the async/await
syntax to write asynchronous code in a synchronous way.
try {
const response = await getData();
} catch (error) {
// Handle error
}
Thanks to the async/await
syntax sugar, you can almost forget that JS is a single-threaded language.
Conclusion
In conclusion, while promises have been a significant improvement over traditional callbacks, async/await
takes
asynchronous programming to the next level. By providing a synchronous style of writing asynchronous code, async/await
has greatly improved the readability and maintainability of code. Its centralized error handling approach and ability to
avoid the overhead of callback functions make it a more elegant and efficient solution for handling asynchronous
operations. With its many advantages, async/await
has become an essential tool for any modern JavaScript developer
looking to write clean, efficient, and maintainable asynchronous code.