npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

catchbuddy

v0.2.0

Published

Simplify error handling in JavaScript with a lightweight utility that organizes results and errors for both synchronous and asynchronous operations.

Readme

Welcome to CatchBuddy! 👋🏻

This package is a wrapper around a common pattern in Javascript: the try/catch statement.

Quick start

Installation

Use your favorite package manager to install CatchBuddy.

npm install catchbuddy

Usage

Problem

Let's start with an example of a common try-catch statement in Javascript.

try {
    mightThrow();
} catch (err) {
    console.error(err);
}

If you plan on keeping your application as simple as this, you might not need catchbuddy. Once you start adding more calls that might throw, handling errors become messy really quickly.

try {
    mightThrow();
    mightThrowSomeError();
    mightThrowAnotherError();
} catch (err) {
    console.error(err);
}

Now you have three different errors to handle. Sure, you could use an if statement or switch through them but you can see that this becomes a pain in the ass really quickly. Let's say the third function call throws an error, and you'd still want to handle the results of the first two successful calls. Well, you can't really do that because of how the try-catch blocks are scoped.

try {
    const result1 = mightThrow();
    const result2 = mightThrowSomeError();
    const result3 = mightThrowAnotherError(); // throws an error

    doSomethingWithResults(result1, result2, result3);
} catch (err) {
    console.error(err);
    // result1, result2 and result3 are undefined here
}

What if you wrap the three calls in their own try-catch blocks?

try {
    const result1 = mightThrow();
} catch (err) {
    console.error(err);
}

// Can't access result1 here.

try {
    const result2 = mightThrowSomeError();
} catch (err) {
    console.error(err);
}

// Can't access result1 and result2 here.

try {
    const result3 = mightThrowAnotherError(); // throws an error
} catch (err) {
    console.error(err);
}

// result1, result2 and result2 are undefined here.
doSomethingWithResults(result1, result2, result3);

Solution

Let's apply resolveSync from CatchBuddy on the last example.

import { resolveSync } from "catchbuddy";

const [err1, result1] = resolveSync(mightThrow());
const [err2, result2] = resolveSync(mightThrowSomeError());
const [err3, result3] = resolveSync(mightThrowAnotherError());

if (err1) {
    console.error("We have a problem with mightThrow.", err1);
}
if (err2) {
    console.error(
        `We have a problem with mightThrowSomeError, but ${result1} is fine!`,
    );
}
if (err3) {
    console.error(
        `Oops, mightThrowAnotherError failed, but ${result1} and ${result2} are fine!`,
    );
}

// We can do anything we like with either result or error. Great! :)
doSomethingWithResults(result1, result2, result3);

You see, with resolveSync, you can handle errors and results in a more organized way. You can also access the results of the successful calls outside of the try-catch block.

Handling Async Function Calls

CatchBuddy is not limited to synchronous operations. It can also be used to simplify asynchronous function calls, such as those that return a promise. Here’s how you can handle async function calls with resolve:

Problem

When dealing with async operations, you often use try/catch blocks with await:

async function handleAsyncOperations() {
    try {
        const result1 = await asyncMightThrow();
        const result2 = await asyncMightThrowSomeError();
        const result3 = await asyncMightThrowAnotherError();
        doSomethingWithResults(result1, result2, result3);
    } catch (err) {
        console.error("One of the async operations failed", err);
    }
}

If one of the async operations throws an error, the entire block fails, and the subsequent operations are not executed. This makes it hard to work with partially completed results.

Solution

With resolve, you can handle async operations more granularly without worrying about the scope of a try/catch block. It takes advantage of the promise's ability to resolve errors and values consistently. Here's how you could rewrite the above logic:

import { resolve } from "catchbuddy";

async function handleAsyncWithResolve() {
    const [err1, result1] = await resolve(asyncMightThrow());
    const [err2, result2] = await resolve(asyncMightThrowSomeError());
    const [err3, result3] = await resolve(asyncMightThrowAnotherError());

    if (err1) {
        console.error("Error in asyncMightThrow:", err1);
    } else {
        console.log("Result from asyncMightThrow:", result1);
    }

    if (err2) {
        console.error("Error in asyncMightThrowSomeError:", err2);
    } else {
        console.log("Result from asyncMightThrowSomeError:", result2);
    }

    if (err3) {
        console.error("Error in asyncMightThrowAnotherError:", err3);
    } else {
        console.log("Result from asyncMightThrowAnotherError:", result3);
    }

    // All results (successful or not) are still accessible here
    doSomethingWithResults(result1, result2, result3);
}

Benefits of Using resolve with Async

  • Error Isolation: Errors in one async function do not affect others. Each function's result or error is handled independently.
  • Simplified Syntax: No nested try/catch blocks or complex chaining of promises.
  • Access to Partial Results: You can access the successful results even when some operations fail, which is particularly useful in workflows that can continue despite some errors.

Example

Here's a full example with mocked async functions to demonstrate:

import { resolve } from "catchbuddy";

async function asyncMightThrow() {
    // Simulated async success
    return "Result from asyncMightThrow";
}

async function asyncMightThrowSomeError() {
    // Simulated async failure
    throw new Error("Something went wrong in asyncMightThrowSomeError");
}

async function asyncMightThrowAnotherError() {
    // Simulated async success
    return "Result from asyncMightThrowAnotherError";
}

async function handleExample() {
    const [err1, result1] = await resolve(asyncMightThrow());
    const [err2, result2] = await resolve(asyncMightThrowSomeError());
    const [err3, result3] = await resolve(asyncMightThrowAnotherError());

    if (err1) console.error(err1);
    else console.log(result1);

    if (err2) console.error(err2);
    else console.log(result2);

    if (err3) console.error(err3);
    else console.log(result3);
}

CatchBuddy simplifies error handling for both synchronous and asynchronous operations, making your code easier to read and maintain.

Contributing

If you have any ideas on how to improve CatchBuddy, feel free to open an issue or a pull request. We're always open to new ideas and improvements.