cover-img

Common mistakes in using JavaScript Promises

As beginners of JavaScript Promises, you may make a few common mistakes. This article to help you identify them and start using them in the right way.

20 July, 2022

19

19

3

Hello friends 👋. So far, we have learned a lot about JavaScript asynchronous programming and promises.

If you are new to the series, please check out the previous articles. In this article, we will look into a list of common mistakes we make in using promises.

1. Looping with Promises

The most common mistake is handling promises inside a loop(for, forEach, and all other cousin loops). We use promises to accomplish asynchronous(async) operations. Async operations take time to complete. How much time? It depends on many factors, and we can not guarantee.

So, when we handle multiple promises within a loop, we need to be a bit careful. Some promises may take longer to resolve. The rest of the code inside the loop may finish execution early and may cause undesirable behaviors. Let's understand it with a simple example.

I want to fetch a few GitHub details of my three dear friends(Savio Martin, Victoria Lo, and Usman Sabuwala]) along with mine.

First, Let's create an array of their GitHub user ids.


Now, let's create a simple function to call GitHub API to fetch user details by user id.


So let's loop?


We use the for-loop to loop through the user id array and call the fetchData() method. The fetchData() method returns a promise with a response. So we get the response value using the .then() handler method. The response value is another promise. Hence we need to invoke .then() one more time to fetch the intended data.

The fetchData() performs an asynchronous operation, and you can not ensure the sequence of output in this case. So, there are chances we get the output in a different order than the user id passed to the fetch method. Our order was savio, victoria, max-programming, and atapas. However, one possible output order could be,

for loop output

Let's fix this. Now we will change the loop function a bit to use our favorite async/await keywords. In this case, the control waits when it encounters the await keyword. Hence we have an assurance of getting the first user data and then move to the second one, then the next one, and so on.


Here is the output(always),

fetch async

But, still, there is a problem! Fetching each of the user details should be an asynchronous activity. Also, these are unrelated promises, and they must run in parallel to produce a result. In the example above, the promise execution is synchronous.

To fix that, use the Promise.all([...]) or Promise.allSettled([...]) APIs. They both take an array of promises, run them in parallel, and return the result in the same order of the inputs. The total time taken by these API methods depends on the max time taken by any of the input promises. It is far better than executing them sequentially.


Promise API output array(check the order of elements in the array is the same as the input order),

promise all output array

The output we print in the browser console,

promise all output

Conclusion: Use promise APIs(.all or .allSettled) to handle multiple unrelated promise executions than using loops.

2. Promise Chain vs. No Chain

When using a promise chain, do NOT repeat the promise in front of the .then, .catch handler methods.

Let's create a promise that resolves a value of 10.


Now, let's form a proper promise chain. Here we return and move the values down the chain.


So, the output we see in the console is the value 190. Now take a closer look at the code below. Here we use the promise ten in front of all the .then() methods. We are NOT forming a chain here.


Always remember this,

chain-no-chain.png

Conclusion: Do not be confused with a NO chain over a promise chain.

3. (Not)Handling Errors with Promises

The most straightforward way to handle errors in promises is with the .catch() hander method. But when we forget to use it, we may mishandle an error scenario in our code.

Here is a simple function that takes a number as an argument. If it is an even number, it resolves by returning a string, Even. In case of an odd number, the promise rejects with an error message.


First, let's pass an even number, 10.


Alright, the output is expected as Even. Now, let us pass an odd number to the function.


We will get the uncaught error,

uncaught error

As we discussed, the best way is to use the .catch() always with one or multiple .then() to handle errors.


Conclusion: Always use .catch() to handle errors even if you are very sure of no error chances!

4. Missing a function in .then() handler

You may sometimes miss using the function as a parameter of the .then() handler. Please note, the .then() method takes two callback functions as arguments. The first one is to handle the resolve case and the second one for the rejected case.

But if we miss using the callback function and use any other value instead, it doesn't give us the expected output. Can you please guess the output of the following code snippet? Will it be Hello or World?


It will be Hello as the first .then() method doesn't use a function callback. The previous result just falls through.

Conclusion: Do not forget the function as an argument to the .then() handler.

5. Using Promises for Synchronous Operations

Another common mistake we make is using the synchronous(in-memory) method call inside a promise and making the program execution slow.

Consider, we have an object(a user cache) to get the user details using the email id as a key.


Now, check out the following function. It first finds if the user is in the cache. If not, then makes the call to fetch the data and update the cache. If it is found, just print it. The following code works, but we are delaying our decision by putting the code of user retrieval from cache inside the promise.


We can rather do this,


Conclusion: Do not slow down decision-making by putting the synchronous operation inside a promise.

6. Using unnecessary try-catch with promises

Last but not least. Please don't do this. It is redundant to use the try-catch inside a promise executor function. We have .then() and .catch() to handle results and errors respectively.


Better way,


**Conclusion: ** The try-catch inside a promise is just a waste of time and effort.

That's all for now. Do not forget to have a loot at the GitHub repository with all the source code used in this article,

GitHub Repository

I hope you found this article insightful. Please like/share so that it reaches others as well.

Let's connect. You can follow me on,

javascript

19

19

3

javascript

Tapas Adhikary
Educator @tapaScript | Teaching JavaScript/React/FullStack | Writer | YouTuber | Founder CreoWis

More Articles

Showwcase is a professional tech network with over 0 users from over 150 countries. We assist tech professionals in showcasing their unique skills through dedicated profiles and connect them with top global companies for career opportunities.

© Copyright 2024. Showcase Creators Inc. All rights reserved.