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

mobx-failable

v0.1.0

Published

Simplified error handling in MobX

Downloads

8

Readme

mobx-failable

A reactive MobX counterpart to a promise, similar to the fromPromise function from mobx-utils or failable, with various built-in MobX computed properties and actions. The basic class Failable models the three promise states: pending, success, and failure.

Installation

This package is on npm: just run npm install --save mobx-failable. TypeScript support works out of the box.

API

The API surface is still in flux, but Failable is the baseline class to use, whereas Loadable extends the basic semantics of Failable. Both of these classes implement the interface Future, which allows you to treat Failable and Loadable similarly, barring the small semantic differences.

Failable<T>

The baseline Failable consists of three states: pending, success, and failure. When initialized, it starts out in the pending state:

const f = new Failable<number>();
f.isPending; // == true

Each of the states correspond to a phase in a promise's lifecycle: pending is analogous to when a promise is just created, success correponds to when a promise resolves, and failure is akin to when a promise is rejected.

The following computed properties reflect which state the Failable is in:

  • isSuccess: boolean
  • isFailure: boolean
  • isPending: boolean

By themselves these properties are not very useful. To retrieve or set the relevant data, consult these methods:

  • success(value: T): this, a MobX action that, given the provided value, switches the state to success.
  • failure(error: Error): this, a MobX action that, given the provided error, switches the state to failure.
  • pending(): this, a MobX action that switches the state to pending.
  • accept(p: Promise<T>): this, a method that "accepts" a promise. First, it immediately switches the state to pending. Then, if the promise resolves, it switches the state to success. Otherwise, if the promise is rejected, it switches the state to failure.
  • match(options): A | B | C, a method that takes a bag of callback options and invokes one of them, depending on the state. The return value of the invoked callback is then passed through. The success callback takes a value, the failure callback takes an error, and the pending callback takes nothing.
  • successOr<U>(defaultValue: Lazy<U>): T | U, a method that is a shorthand for a call to match where the success case merely passes through the value and the remaining cases fall back to the provided default value. See Lazy<T> for how the default value is evaluated.
  • failureOr<U>(defaultValue: Lazy<U>): T | U, a method that is like successOr, except it is biased towards the failure state.

A typical usage of Failable looks like:

import {Failable} from 'mobx-failable';

function getUser(id: string): Promise<User> {
  return fetch(`/user/${id}`).then(parseUser, parseError);
}

class State {
  userId: string;

  @observable user = new Failable<User>();

  constructor(id: string) {
    this.userId = id;
  }

  fetch(): void {
    this.user.accept(getUser(this.userId));
  }

  @computed get userName(): string {
    return this.user.successOr('Unknown');
  }
}

// Use State class in a React component, for example

Lazy<T>

A lazy value is either a function, which should take no arguments and return a value, or it is a plain value. Note that a function that takes one or more arguments is not a valid lazy value, but there are no runtime or type system checks to enforce this. The type definition is T | (() => T).

  • Lazy.force(l: Lazy<T>): T evaluates the given lazy value. If the given value is not a function, it is returned as-is. If it is a function, then it is invoked, and its return value is passed through.

Loadable<T>

A Loadable recategorizes and extends the three states of Failable into six states. There are now two dimensions: availability (none, value, error) and flight (busy, idle).

Availability / Flight | Idle | Busy -- | -- | -- None | Empty | Pending Value | Success | Reloading Error | Failure | Retrying

  • Flight refers to whether or not a request is in flight. Busy means such a request is in progress, whereas idle means nothing is in progress.
  • Availability refers to the sort of data possessed. None means there is no data, value means the intended data succeeded in loading, and error means the intended data failed to load. This is similar in shape to (but not same as) the original three states.

Rationale

The biggest flaw of Failable is that it models a single request cycle. By definition, if it is pending, it cannot have data. This contradicts most user interfaces, which are driven by multiple request cycles. For example, when viewing an inbox, initiating a refresh will show an activity indicator, but existing data does not disappear.

Accept-oriented workflow

The intended usage for Loadable is centered around using accept. In fact, the most material differences between Loadable and Failable are:

  • match(options): A | B | C, a method that takes a bag of callback options and invokes one of them, depending on the availability. The return value of the invoked callback is then passed through. The success callback, called when the availability is value, takes (value, loading?). The failure callback, called when the availability is error, takes (error, loading?). The pending callback, called when the availability is none, takes (loading?).
  • accept(p: Promise<T>): this, a method that "accepts" a promise. First, it immediately switches the flight to busy. Then, if the promise resolves, it switches the state to success. Otherwise, if the promise is rejected, it switches the state to failure.

Sequence

Of the three availabilities, the none availability only occurs once per the lifetime of a loadable. The sequence of events is as follows:

  • The loadable is initialized. It begins in the empty state.
  • An operation begins, yielding a promise. This promise is then accepted into the loadable, so it enters the pending state.
    • The promise fulfills, so the loadable enters the success state.
    • The promise rejects, so the loadable enters the failure state.
  • Another operation begins, yielding a promise of the same type. This promise is once again accepted into the loadable.
    • If the loadable was in the success state, it now enters the reloading state.
    • If the loadable was in the failure state, it now enters the retrying state.
    • Once the promise fulfills or rejects, the loadable again enters either the success state or failure state.