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

rah-rah

v2.3.0

Published

Use await while respecting failure cases without exceptions

Downloads

4

Readme

RahRah

Use Javascript await while respecting failure cases without exceptions.

Why does this exist?

If you want to use await and still get data from failure cases, you must use try/catch:

// old way

async function myFunc() {
  let result;
  try {
    result = await someAsyncFunc();
    doSomething(result);
  } catch (e) {
    handleError(e);
  }
}

// new way with rah-rah

import { R } from 'rah-rah';

async function myFunc() {
  const result = await R(someAsyncFunc());

  if (result.good) {
    doSomething(result.ok);
  } else {
    handleError(result.err);
  }
}

// or even

import { R } from 'rah-rah';

async function myFunc(): string {
  const result = await R(someAsyncFunc());

  return (
    result
      .map(doSomething)
      .mapErr(handleError)
      .withDefault('n/a')
  );
}

If you recognize this kind of thing from the Functional Programming world, it's basically Result/Either mapped inside a Promise... or something like that.

Usage

Creation

Insert a call to R between await and your promise:

import { R } from 'rah-rah';

const result = await R(aPromise);
const otherResult = await R(ajaxAsPromise(url));

Did it fail or succeed?

If you use withDefault, map, and mapErr (shown below), you shouldn't need these.

import { R } from 'rah-rah';

async function go(aPromise: Promise<...>) {
  const result = await R(aPromise);
  if (result.good) {
    // ...
  } else { ... }

  // or

  if (result.bad) {
    // ...
  }
}

Raw results

Use result.ok and result.err. If you use withDefault, map, and mapErr (shown below), you shouldn't need these.

import { R } from 'rah-rah';

async function go(aPromise: Promise<...>) {
  const result = await R(aPromise);
  if (result.good) {
    doSomething(result.ok);
  } else { ... }

  // or

  if (result.bad) {
    handleError(result.err);
  }
}

Collapsing errors

Perhaps you don't care about an error? Or you've correctly handled the error, and you'd like to use either a successful value or a default value in the case of a failure:

import { R } from 'rah-rah';

async function go(aPromise: Promise<string>): Promise<string> {
  const result = await R(aPromise);
  return result.withDefault('An error occurred.');
}

If you want the default to use the underlying error value, use applyDefault:

import { R } from 'rah-rah';

async function go(aPromise: Promise<string>): Promise<string> {
  const result = await R(aPromise);
  return result.applyDefault((err: Error) => `An error of type '${err.name}' occurred.`);
}

Changing ("map"ing) successful values

Need to change ("map") the successful value? Use map:

import { R } from 'rah-rah';

async function go(aPromise: Promise<number>): Promise<RahRah<Error, string>> {
  const result = await R(aPromise);
  return result.map(ok => `answer: ${ok}`); // still wrapped in a RahRah object!
}

Changing ("map"ing) failure values

Need to change ("map") the failure value? Use mapErr:

import { R } from 'rah-rah';

async function go(aPromise: Promise<number>): Promise<RahRah<string, number>> {
  const result = await R(aPromise);
  return result.mapErr(err => err.message.toLowerCase()); // still wrapped in a RahRah object!
}

Collapsing errors & results

Perhaps you need to do something with both successful and failure situations, and return an unwrapped value:

import { R } from 'rah-rah';

function double(result: RahRah<Error, number>): string {
  return result.flatten(ok => {
    return `doubled: ${ok * 2}`;
  }, err => {
    informExceptionHandler(err);
    return err.message.toLowerCase();
  });
}

const result = await R(aPromise);
console.log(double(result));

Installation

This library requires TypeScript, with at least es2015 compatibility.

$ npm install typescript --save-dev
$ npm install rah-rah --save

Other similar libraries

await-to-js

await-to-js provides a wonderfully simple API that does nearly the same thing:

import to from 'await-to-js';

const [err, user] = await to(UserModel.findById(1));

The problem is that await-to-js assumes that you'll never want to use null as a real error value; that is, you can never have a null value for err. Similarly, you're disallowed from returning (as unlikely as it is) undefined as your successful value.

These edge cases are nuanced and very unlikely, but they exist. RahRah avoids these edge cases.

License

License terms can be found in the LICENSE file.

Author

RahRah was written by: