rah-rah
TypeScript icon, indicating that this package has built-in type declarations

2.3.0 • Public • Published

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:

Readme

Keywords

none

Package Sidebar

Install

npm i rah-rah

Weekly Downloads

1

Version

2.3.0

License

Apache-2.0

Unpacked Size

40.7 kB

Total Files

12

Last publish

Collaborators

  • vennelakodali
  • listrophy