When comes to asynchronous operation, we always think about JavaScript Promise methods right? But there are other ways we can sort this out. I found the most profound way is async/await
. async
is used when we are writing any asynchronous operation and await
is used when we are waiting for that asynchronous operation.
const getPersons = async () => {
// we are making the actual database ie REST api call
return fetch('persons');
}
const process = async () => {
// we are waiting for persons
const persons = await getPersons();
console.log(persons);
}
There are a number of ways we can handle errors in JavaScript. In this article, we'll talk about the 3 most used ways to handle async/await
error.
1. Promise.catch
We know we can use promises with async
. We'll add a catch block with the asynchronous method.
const getPersons = async () => {
return fetch('http://person')
// here we added a promise catch method
.catch(error => {
//TypeError: Failed to fetch
console.log(error);
});
}
const process = async () => {
const persons = await getPersons();
console.log(persons); // undefined
}
process();
This way we can handle unhandled promise rejection
error. But the downside of this approach is we have to add a catch method for each asynchronous operation.
2. A wrapper of Promise.catch
We can create a wrapper function so that we don't need to add the catch
method of each asynchronous operation.
const asyncWrapper = async (promise) => {
return promise.catch(error => {
console.log(error); //TypeError: Failed to fetch
return error;
});
}
const getPersons = async () => {
return asyncWrapper(fetch('http://person'));
}
const process = async () => {
const persons = await getPersons();
console.log(persons); //TypeError: Failed to fetch
}
process();
It is better hah? So, what we did here? We extract the catch
method from getPersons
to asyncWrapper
. We handle the error inside the wrapper and return the error to the outside to show some error message to the user.
In this approach there are slight difficulties, each and every time we have to check, there is a valid person or not? This is tedious and there is no clear way to know that there is an error. We can solve this problem
const asyncWrapper = async (promise) => {
return promise
.then(result => [null, result])
.catch(error => [error]);
}
const getPersons = async () => {
return asyncWrapper(fetch('http://person'));
}
const process = async () => {
const [error, result] = await getPersons();
console.log(error, result); //TypeError: Failed to fetch, undefined
}
process();
This is way better right? Here we use JavaScript destructing pattern. We add a .then
method and return the success case as [null, result]
. That means, if your asynchronous operation is successful, it will return the result where the error is null
On the other hand, we returned [error]
means the result is undefined
. It is other way around, when error is present there is no result and when the result is present there is no error! In this pattern, we clearly know when an error happened.
3. Promise.allSettled
We know Promise.allSettled
is very powerful method where it shows the reason why your asynchronous operation is failed. If you want to learn more, check this article
https://dev.to/tasnimreza/3-most-powerful-javascript-promise-methods-2g8f
const asyncWrapper = async (promise) => {
const [result] = await Promise.allSettled([promise]);
return result;
}
const getPersons = async () => {
return asyncWrapper(fetch('http://person'));
}
const process = async () => {
const { reason, value } = await getPersons();
console.log(reason, value); //TypeError: Failed to fetch, undefined
}
process();
We use Promise.allSettled
inside the wrapper and await
to finish the job. When the asynchronous operation is finished, it destructing the result to the result array. Because Promise.allSettled
always return array.
Finally we use object destructing to receive the result. As we know Promise.allSettled
return status, reason, value
. Here we ignore the status
because it is not needed.
When the asynchronous operation is failed, reason
is present and value
is undefined. If the call is successful, value
is present and reason
is undefined. In this way we clearly know when the error is present.
Note:
There is a common way to handle error in JavaScript is using try...catch
I skip this because it is quiet well known pattern.
Summery
Thanks for reading and I hope you learn something from this article. If you have any question please let me know in the comments. I hope your code will be much better after using any of these pattern!
Top comments (0)