DEV Community

Cover image for Clean Up Your Code: No More Try-Catch!
Gazi Nahian
Gazi Nahian

Posted on

Clean Up Your Code: No More Try-Catch!

No More Try-Catch in JavaScript

Error Handling Made Easy If you’ve ever had to deal with try-catch in JavaScript, you know it can quickly get messy, especially when working with async operations like fetch. It clutters your code and doesn’t feel as elegant as modern JavaScript should. What if I told you that there’s a cleaner, more readable approach? And what if we could write async code without the hassle of wrapping everything in try-catch?

Let’s dive into an alternative pattern that simplifies error handling in JavaScript, using a concept we could call "error-first destructuring."

The Problem: Try-Catch Everywhere
Take a look at a typical async operation using try-catch:

async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Error fetching data:', error);
    }
}
Enter fullscreen mode Exit fullscreen mode

It’s not terrible, but as the number of async calls grows, so do the try-catch blocks. Your code becomes cluttered with repetitive patterns, making it harder to read and maintain.

The Solution: Error-First Destructuring with a New Operator
Let’s imagine we could improve the pattern. What if you could destructure your fetch result into error and response values, skipping the try-catch and focusing only on handling the outcome? Something like this:

const [err, res] ?= await fetch('https://api.example.com/data');
Enter fullscreen mode Exit fullscreen mode

Looks cleaner, right? We’re imagining a new operator here, the ?= (safe assignment operator for destructuring), which assigns values while keeping potential errors separate. The idea is that the left side could hold [error, result] without needing a bulky try-catch block.

Now, this isn’t real JavaScript syntax (yet!), but let’s break down how this could work and why it’s interesting.

How it Could Work
Imagine fetch returns either an error or a result, wrapped in a tuple-like structure. Using ?=, you could destructure both the error and the response in one clean line:

const [err, res] ?= await fetch('https://api.example.com/data');
if (err) {
    console.error('Error:', err);
} else {
    console.log('Success:', res);
}
Enter fullscreen mode Exit fullscreen mode

Here’s the magic

If the fetch call fails, err is populated with the error, and res is undefined.
If it succeeds, res holds the data, and err remains undefined.
No need for try-catch. It’s concise, easy to follow, and, dare I say, elegant.

Real-World Example with Promise Wrapper
While the ?= operator isn’t yet part of JavaScript, you can mimic this behavior by wrapping your async calls in a utility function. Let’s write a simple wrapper function that returns [error, result] for any promise.

function to(promise) {
    return promise
        .then(data => [null, data])
        .catch(err => [err, null]);
}
Enter fullscreen mode Exit fullscreen mode

Now, you can use it like this:

async function fetchData() {
    const [err, res] = await to(fetch('https://api.example.com/data'));

    if (err) {
        console.error('Error fetching data:', err);
    } else {
        const data = await res.json();
        console.log('Fetched data:', data);
    }
}
Enter fullscreen mode Exit fullscreen mode

That’s already a lot cleaner! No more cluttered try-catch blocks, and the code is still easy to read and maintain. If there’s an error, you deal with it explicitly without wrapping everything in try-catch.

Why You’ll Love This Approach

Cleaner code: By separating concerns (error handling vs. result handling), your code becomes more readable and maintainable.
Less nesting: With this approach, there’s no need for nested try-catch blocks or chained .then calls that can make code harder to follow.
Focus on logic: Your code focuses on the logic itself, rather than constantly switching context to handle errors.
Is This the Future of JavaScript?
While ?= isn’t an official part of JavaScript (yet!), the concept behind it is worth exploring. JavaScript is constantly evolving, and with the growing desire for cleaner and more concise syntax, who knows what’s coming next? In the meantime, using utility functions like to is a powerful pattern you can adopt today for a cleaner async experience.

Wrapping Up
By adopting patterns like error-first destructuring, you can say goodbye to the clutter of try-catch blocks and welcome a more readable, elegant codebase. While ?= remains a fun "what if?" for now, you can start using the to() utility function to mimic this behavior and transform the way you handle errors in your async JavaScript code.

Happy coding, and may your fetch calls always be error-free! 😎

Top comments (0)