Handling API Errors In JavaScript Without Try-catch: A Beginner-Friendly Approach
When working with APIs in JavaScript, you'll often encounter the need to handle errors that arise from network issues, failed requests, or invalid responses. Traditionally, we use try-catch blocks to manage these errors , but sometimes this can clutter your code or make it harder to read. In this article , you'll learn a more elegant approach by returning results and errors in a tuple (array) format, making your code cleaner and easier to maintain.
Key Takeaways:
* What try-catch blocks do
* The limitations of try-catch
* How to return [error, result] tuples using a simple utility function
* How to handle API responses using this pattern
Understanding try-catch
Normally, when you make a request to an API, it looks like this:
const _fetchData = async () => {
try {
const response = await fetch('https://openforhiring/api');
const data = await response.json();
console.log('Success:', data);
} catch (error) {
console.error('Failed to fetch:', error);
}
};
_fetchData();
Here, we use a try block to attempt to fetch data, and if the fetch fails, the error is caught in the catch block. While this works, it's not always the cleanest way to handle errors, especially if you’re working with multiple async operations.
The Limitations of try-catch
1. Verbosity: If you're dealing with many async operations, wrapping every one of them in a try-catch can make your code harder to read.
2. Error Handling Scopes: Sometimes, you want to handle errors directly where they happen, without wrapping too many things in try-catch blocks.
So how do we simplify this? That's where the Tuple pattern comes in!
The Tuple Pattern: [error, result] Instead of using try-catch everywhere, we can create a function that catches the error internally and returns it as part of a tuple (array). This way, you can handle errors and results at the same place without needing explicit try-catch blocks.
Here’s how you can achieve it.
Initial Step: Create a _to() Utility Function The _to() function will take a promise (like your API request) and return an array with two values: the first one is the error (if there is any), and the second is the result (if the promise resolves successfully).
const _to = async (promise) => {
try {
const result = await promise;
//This for Success: No error, return result
return [null, result];
} catch (error) {
//This for Error: Error occurred, return error
return [error, null];
}
};
Second Step: Use the _to() Function to Fetch API Data Now that we have the to() function, let's use it to handle an API request. This approach will help us easily check for errors or success without using a try-catch block.
const _fetchData = async () => {
const [error, result] = await _to(fetch('https://openforhiring/api'));
if (error) {
console.error('Failed to fetch data:', error);
} else {
const data = await result.json();
console.log('Success:', data);
}
};
_fetchData();
How This Works:
- Error Handling: If there’s an error (like a network issue), the _to() function catches it and returns it in the first part of the tuple (error). We can then check for this error and handle it appropriately.
- Successful Response: If the fetch succeeds, the result is placed in the second part of the tuple (result), which can then be used to process the response (like converting it to JSON).
Benefits of Using This Pattern
1. Cleaner Code: You don’t need multiple try-catch blocks cluttering your code.
2. Consistency: You always get [error, result], making it easier to reason about what’s happening in your code.
3. Better Control: You can decide how to handle errors and results in a single, consistent way.
Take a look at the example below;
Let’s say you have an API that returns a list of users. Here’s how you can fetch that data using the tuple pattern:
const _fetchUsers = async () => {
const [error, response] = await _to(fetch('https://opentowork.com/api/users'));
if (error) {
console.error('Error fetching users:', error);
return;
}
const users = await response.json();
console.log('User data:', users);
};
_fetchUsers();
This will either print the list of users or log the error if something goes wrong.
Bringing It All Together
By using the tuple pattern with [error, result], you can simplify error handling in your JavaScript code. This is particularly useful when working with async operations like fetching APIs, where handling errors properly is critical. No more repetitive try-catch blocks. Just one clean function to manage both success and failure. This pattern works well in many scenarios, not just for APIs. You can use it for any promise-based operation and keep your code simple, readable, and consistent.
Now, go ahead and implement this pattern in your next project. You’ll find it makes your code much more maintainable!
Comment, like and feel free to share. Thanks.
Subscribe to my newsletter
Read articles from Abdulhakeem Gidado directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by