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 🙏

© 2024 – Pkg Stats / Ryan Hefner

invoke-guarded-callback

v1.0.0

Published

"Pause on exceptions"-friendly code execution

Downloads

1

Readme

invokeGuardedCallback

Description

invokeGuardedCallback is a helper function that invokes a given callback, capturing an error if it occurs:

invokeGuardedCallback(
  () => {
    doWork();
  },
  (error) => {
    // Called if there is an error thrown during `doWork`
  }
);

This is similar to a try/catch:

try {
  doWork();
} catch (error) {
  // Executes if there is an error thrown during `doWork`
}

The purpose of invokeGuardedCallback is to improve developer experience when debugging in DevTools.

When debugging JavaScript code, you typically want the debugger to be configured to "pause on exceptions." This ensures that, when there is an uncaught error, the debugger stops right when the error occurs. When a try/catch is used, it prevents pausing on any exceptions that occur within the try block. This behavior intends to be helpful; the debugger assumes that you aren't interested in pausing, since the catch block was set up to handle errors.

The debugger's heuristic is not always desirable. Imagine you are writing a JavaScript library that invokes code provided by developers. You might want to use a try/catch to handle any errors coming from that untrusted code. But the developers who provided the code may be frustrated with their own debugging experience. The library's try/catch would prevent "pause on exceptions" from working well for developers using the library.

invokeGuardedCallback invokes a callback in a way that captures errors while still allowing the debugger to pause directly on exceptions.

Inspiration

This API is heavily inspired from React. React has its own internal invokeGuardedCallback API that is used to wrap calls into component code written by developers. It allows React to handle errors without adversely affecting debugging behavior for developers.

This package implements a similar API without any tie to React, generalizing the idea for reuse.

Compatibility

The intent is to work in "most" browsers (anything reasonably modern) and fallback to try/catch for any unsupported browser. Internet Explorer 11 should work.

Node and Deno do not work currently. They should fallback to try/catch.

Installation

Install invoke-guarded-callback from npm.

npm i invoke-guarded-callback

Usage

Basics

The most basic usage is shown below.

const value = invokeGuardedCallback(
  () => computeValue(),
  (error) => {
    /* Do something with `error` */
  }
);

You might pass the error into some sort of logging/tracing infrastructure...

const value = invokeGuardedCallback(
  () => computeValue(),
  (error) => Logger.log(error)
);

Or save and handle the error locally in the calling code...

let invokeError;
const value = invokeGuardedCallback(
  () => computeValue(),
  (error) => {
    invokeError = error;
  }
);
if (invokeError) {
  // Recover/log the error.
  // Note that the return `value` will be undefined if there was an error.
}

Tips

Use invokeGuardedCallback for development only. It is not recommended in production due to potential performance impact.

Consider some sort of check to see whether you are in production.

if (process.env.NODE_ENV === "production") {
  // try/catch
} else {
  // invokeGuardedCallback
}

Create your own wrapper API around invokeGuardedCallback. Your wrapper can incorporate the production check mentioned above, for example. It could also help standardize how you log errors from untrusted callbacks across a codebase.

How does it work?

The implementation is based around EventTarget.dispatchEvent. This API is traditionally used to dispatch events to DOM elements, and one of its characteristics is that errors won't propagate out of the dispatchEvent call. When errors do occur, they end up going to a global error handler (window.onerror or similar).

With this behavior, the clever trick (again, courtesy of React) is that we can:

  1. Attach a global error handler.
  2. Dispatch an event against an event target, where the event triggers an event handler that runs the callback.
  3. If an error occurs in the callback, we can "catch" it in the global error handler.

License

MIT License