Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Mastering Asynchronous Programming in JavaScript: Unraveling the Magic of async/await, Promises, and More

Posted on Sep 23 Picture this: You're at a bustling coffee shop, eagerly awaiting your favorite brew. As you stand in line, you notice a peculiar sight. Instead of waiting their turn, people are multitasking effortlessly. Some chat with friends, others read newspapers, and a few even engage in a friendly game of chess—all while their coffee orders are processed behind the scenes. In this coffee shop, everyone is in perfect sync with their caffeine fix, but what if I told you that JavaScript, your trusty programming language, could function in much the same way? Welcome to the world of Asynchronous Programming in JavaScript, where code can juggle multiple tasks without missing a beat. It's a bit like a coffee shop where your code can chat with databases, read files, and fetch data from the web—all while serving up a delightful user experience.In the realm of modern web development, where user expectations are higher than ever, the ability to handle multiple tasks simultaneously is crucial. Enter asynchronous programming in JavaScript, a paradigm that has revolutionized how we write code for the web. At its core, asynchronous programming allows your JavaScript code to efficiently manage tasks that might take time to complete, such as fetching data from an API, reading files, or performing database operations, all without blocking the main execution thread.In this article, we embark on a journey to demystify the intricacies of asynchronous programming in JavaScript. We'll explore the power duo of async/await functions and the ever-reliable Promises, diving deep into their workings and real-world applications. Whether you're a seasoned JavaScript developer looking to sharpen your skills or a newcomer eager to grasp the fundamentals, you'll find valuable insights here to help you master the art of asynchronous programming.So, grab your favorite beverage, settle in, and get ready to unlock the true potential of JavaScript's asynchronous capabilities. By the end of this article, you'll be equipped with the knowledge and confidence to harness the magic of async/await, conquer Promises, and navigate the nitty-gritty of asynchronous programming in JavaScript with ease.Asynchronous programming is a programming paradigm and technique that allows tasks or operations to be executed independently and concurrently, without waiting for the previous task to complete before starting the next one. In asynchronous programming, a program can initiate a task and then continue executing other tasks without blocking, or waiting for, the completion of the initial task. This approach is particularly valuable in scenarios where certain tasks may take a variable amount of time to finish, such as network requests, file I/O operations, or user interactions. By performing these tasks asynchronously, a program can remain responsive and efficient, ensuring that it doesn't freeze or become unresponsive while waiting for time-consuming operations to finish.Javascript in particular uses asynchronous programming extensively, making use of mechanisms like Promises, async/await, and callback functions to manage asynchronous tasks and maintain a responsive user experience. I will start by using promises, then to async/await then back to promises for some use cases.A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.A Promise is in one of these states:⦁ Pending: initial state, neither fulfilled nor rejected.⦁ Fulfilled: meaning that the operation was completed successfully.⦁ Rejected: meaning that the operation failed.The eventual state of a pending promise can either be fulfilled with a value or rejected with a reason (error). When either of these options occurs, the associated handlers queued up by a promise's .then method are called. If the promise has already been fulfilled or rejected when a corresponding handler is attached, the handler will be called, so there is no race condition between an asynchronous operation completing and its handlers being attached. A promise is said to be settled if it is either fulfilled or rejected, but not pending.First, let's create a promise object using the new keyword..The promise constructor takes in a callback function with two arguments, the first is called when the promise is fulfilled while the second is for when the promise is rejected(note that the naming of the arguments is for readability, you can use any naming of your choice).. In both arguments, the message you want to pass in is what is received on fulfillment or rejection.Now let's move to chained promises..The methods Promise.prototype.then(), Promise.prototype.catch(), and Promise.prototype.finally() are used to associate further action with a promise that becomes settled. As these methods return promises, they can be chained. Meaning .then() returns a newly generated promise object, which can optionally be used for chaining; for example:Processing continues to the next link of the chain even when a .then() lacks a callback function that returns a Promise object. Therefore, a chain can safely omit every rejection callback function until the final .catch() and we have .finally(). So we can have something likeThis picture explains promises graphicallyAlso, we have Promise concurrency which gives more power to promises, and that will be discussed in the later part of this article.The async function declaration creates a binding of a new async function to a given name. The await keyword is permitted within the function body, enabling asynchronous, promise-based behavior to be written in a cleaner style and avoiding the need to explicitly configure promise chains. In clearer terms, async/await helps us to achieve cleaner code over the chains of promises. Consider the following compared to the chains of promises:We will consider more complex and real use cases of async/await in the application section of this article.Take note :⦁ await is only valid on promise, if a function does not return a promise, it's invalid to use await even though it does not break your app, but for the readability of your codebase stay away. ⦁ await keyword can be used within the async function and also at the top level of modules too.Here is an example of a top-level awaitA practical use case of this is when you want to load a file that returns a promise in your .mjs file:From the above code snippet, we have two different approaches, and async/await seems to be cleaner, you won't realize this until you have many stuff to handle in your application.Let's step up the game for instance when you want to make multiple network requests that your app essentially needs... Let's illustrate our approach to this.The time taken to execute this functionIn this case, each request is independent of another, and what we are doing is that after a network request is done, that's when the next request can be made, which is unnecessarily going to make your app slow down, this method is best when each network request is dependent of data coming from another... There is a better approach to this by making parallel requests, here we can now talk about Promise concurrency; we have Promise.all, Promise.allSettled, Promise.any, Promise.reject each as their use cases.Promise.all: Fulfills when all promises are fulfilled; rejects when any of the promises are rejected.Promise.allSettled: Fulfills when all promises settle.Promise.any: Fulfills when any of the promises fulfills; rejects when all of the promises are rejected.Promise.race: Settles when any of the promises settles. In other words, fulfills when any of the promises fulfills; rejects when any of the promises are rejected.In this case, we will be using .allSettled over the .allTime taken for the function to executeRunning each of these cases differently, you'll see from the time logged in the console the latter is faster than the former and as an engineer, every microseconds counts.We need to touch another use case which is having tasks that require us to perform asynchronous actions in an array, this can be quite brain-tasking but here is an example and the fastest approach we can take..Let's say we have an array of delivery boxes sent to the backend, and each box contains an array of items and each item has a value of productId, we need to get some specific detail of the product from our database, and in the end we want to return the product details of each product in items for every boxLet's have our code...We needed to have multiple Promise.all because we are dealing with a task that has to do with a multidimensional array kind of thing, and this proves to be arguably the fastest approach to this kind of problem.There are so many other use cases of asynchronous programming, in fact, a lot of Web APIs are built on promises e.g. WebRTC, WebAudio, etc... As a software engineer asynchronous programming is very important and I hope with this article you have been able to learn more about asynchronous programming with Javascript. Thank you for reading this article, you can share what topic you want me to write on in my next article. Templates let you quickly answer FAQs or store snippets for re-use.Great work! Thank you Dumebi Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse Salah Eddine Lalami - Sep 18 David Rueda - Sep 14 Vinit Gupta - Sep 10 Mysterio - Aug 21 Once suspended, oluwatobi_ will not be able to comment or publish posts until their suspension is removed. Once unsuspended, oluwatobi_ will be able to comment and publish posts again. Once unpublished, all posts by oluwatobi_ will become hidden and only accessible to themselves. If oluwatobi_ is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Oluwatobi Adedeji . They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag oluwatobi_: oluwatobi_ consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging oluwatobi_ will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Mastering Asynchronous Programming in JavaScript: Unraveling the Magic of async/await, Promises, and More

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×