Git Product home page Git Product logo

error-causes's Introduction

Error Causes

Simple error handling based on standard JavaScript error cause.

Handling errors should be easier. Imagine if you could do this:

const [fetchErrors, handleFetchErrors] = errorCauses({
  NotFound: {
    code: 404,
    message: "The requested resource was not found",
  },
  MissingURI: {
    code: 400,
    message: "URI is required",
  },
});

fetch(uri).then(handleFetchErrors({
  NotFound: ({ name, code, message }) =>
    // 404 NotFound: The requested resource was not found
    console.log(`${ code } ${ name }: ${ message }`),
  MissingURI: ({ message }) => console.log(message), // URI is required
}));

With Error Causes, you can. When you build an API or SDK, you can define the errors that can occur and export both the possible error causes, and a function to handle them that users can pass their own handlers to. It's a nice way to document your API with live code and make it easy for users to handle errors.

Error Causes also makes it easy to throw errors with a named cause:

const { NotFound, MissingURI } = fetchErrors;

if (!uri) throw createError(MissingURI);

Getting Started

Install with npm:

npm install error-causes

Or install with yarn:

yarn add error-causes

Why Error Causes?

For every asynchronous API, it's a good idea to define and document the various error causes that might arise. How can a caller distinguish an error caused by bad input from an error caused by a network failure?

One common solution in JavaScript is to use custom error types and the instanceof operator to distinguish between different error causes in calling code. That is a bad idea because JavaScript uses isolated memory realms for security, and instanceof always fails across memory realms (e.g., it will always fail when testing an instance in a child iframe against a constructor in the parent frame, or vice versa). It's also a bad idea because errors can be serialized, deserialized, and rethrown, which could break the instanceof lookup. In other words, the instanceof approach works most of the time, but when it doesn't it can cause a lot of wasted debugging time.

Another common solution is to branch based on the text of the error message. That's a bad idea because error messages are likely to change, and may even be localized, making them an inapropriate basis for conditional branching.

Traditionally in both hardware and software engineering, conditional branching for error handling is done using error codes instead of types. For example, the ubiquitous HTTP status codes.

Unfortunately, JavaScript never standardized the inclusion of an error code. Adding your own involves subclassing or extending the error object in non-standard ways, and there was never a way to pass a cause or structured metadata to the Error constructor - only a message. Until ECMAScript 2022 added the error cause parameter to the Error constructor.

That helps a little, but handlers still have to manually destructure causes.

Under the hood, error-causes constructs a structured cause property for thrown errors that it can then use to automatically match in the error handler:

type Cause = {
  name: String,
  message: String
  code: Any,
  stack: String,
  cause: Cause, // You can use this to reference the original error
}

API

errorCauses

(options: ErrorCausesOptions) => [
  ErrorCausesOptions,
  (CausedError) => Void
]

Takes options and returns an object of error causes keyed by error name, and a function that takes a match object of error handlers, and returns a function that takes an error and automatically dispatches the matching error handler.

The returned cause objects can be passed to the createError factory to create the corresponding CausedError, or used to manually switch over an error if you prefer not to use the error matcher.

// Can include any number of ErrorName: Cause pairs
type ErrorCausesOptions = {
  [ErrorName]: Cause // See above
}

createError

(errorOptions: ErrorOptions) => CausedError

In order to be handled by the automatically generated handler, errors must have a cause property. The built-in syntax to create a caused error looks like this:

const notFoundError = new Error('The requested resource was not found', {
  cause: {
    name: 'NotFound',
    code: 404
  }
);

That's not too bad, but we think this is much nicer:

const notFoundError = createError({
  name: 'NotFound',
  code: 404,
  message: 'The requested resource was not found,
});

Options:

type errorOptions = {
  name: String,
  code: Any,
  message: String,
  cause: Any,
  stack: String,
  ...rest: * // Mixed types allowed
}

Sponsors

This project is made possible by EricElliottJS.com and DevAnywhere.io. If you would like to sponsore this project as well, reach out.

License

MIT

error-causes's People

Contributors

ericelliott avatar renovate[bot] avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.