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

resultify

v1.1.2

Published

Handle errors with async/await without try/catch.

Downloads

26

Readme

resultify

Handle errors with async/await without try/catch.

Example

const fs = require('fs')
const { resultify } = require('resultify')

const readFile = resultify(fs.readFile)

async function main () {
  const { err, data: file } = await readFile(__filename, 'utf8')
  if (err) {
    console.error('oops', err)
    return
  }

  console.log('echo file')
  console.log(file)
}

The resultify library is exactly the same as util.promisify except the promise will return { err, data } instead of throwing.

The promise returned from resultify will never throw / reject.

This module is great for people that like async/await and do not like try/catch.

Motivation

There are good and part parts to Promises. async & await is definitely one of the good parts.

Unfortunately promises merge Operational & Programmer errors into a single error that you have to try / catch for.

Go has a really nice pattern for handling errors explicitely

buf, err := ioutil.ReadAll(f)
if err != nil {
  return nil, errors.Wrap(err, "read failed")
}

Their approach is to use multiple return values, unfortunately multiple return values do not exist in javascript but we do have multiple arguments to functions which is why the function done(err, value) {} callback has always worked nicely.

Using destructuring

One language feature JavaScript does have is destructuring so we can do const { err, data } = await x()

async function readFile (path) {
  const { err, data: fd } = await open(path, 'r')
  if (err) {
    return { err: new Error('open failed') }
  }

  const buf = Buffer.alloc(64 * 1024)
  const { err: readErr } = await read(fd, buf, 0, buf.length, 0)

  const { err: closeErr } = await close(fd)
  if (closeErr) {
    return { err: new Error('close failed') }
  }

  if (readErr) {
    return { err: new Error('read failed') }
  }

  return { data: buf }
}

Using { err, data } as the API for all your async functions works nicely and makes error handling explicit and removes throw, try & catch.

This is great for your application code but how do you interact with the echo system of modules in core & node_modules ?

Using first & third party modules

The package resultify is very similar to util.promisify but instead of returning a promise that rejects on err it will return a Promise that always resolves to { err, data }.

Now you can do :

const fs = require('fs')
const { resultify } = require('resultify')

const open = resultify(fs.open)
const read = resultify(fs.read)
const close = resultify(fs.close)

If you have a third party library from NPM, like node-fetch you can use the resultifyP function to wrap it into returning a Promise that returns { err, data }

const fetchAsPromise = require('node-fetch')
const { resultifyP } = require('resultify')

const fetch = resultifyP(fetchAsPromise)

async function main() {
  const { err, data: res } = await fetch('https://nodejs.org/en/')
  assert.ifError(err)

  assert.ok(res)
  assert.equal(res.status, 200)
}

See also

If you want to read some of my other related projects; check out:

Yet another module ???

The source code is pretty small, do you really need a module for a bit of wrapper try / catch code ???

Honestly, we don't need this module in any of our apps, we just need a few strategic try / catch {} statements to make the rest of the application use { err, data } = await x() natively.

However, it's pretty hard to document this pattern, this README seems like a fantastic place to document the IDEA itself.

Feel free to use { err, data } = await x() without importing this library, in fact please do !

Documentation.

This package implements & exports three functions, resultify, resultifyP and resultifySync.

The resultifySync function exists mostly as a helper to wrap around JSON.parse in case you want to disallow try / catch in your codebase.

const fn = resultify(original)

Calling resultify on a function returns a promise returning function similar to how util.promisify works.

The original function is expected to be a normal nodejs cb last function, i.e. the last argument is a callback.

The returned function fn does not take a callback and instead returns a promise that resolves to { err, data } which are the two arguments for the callback.

const fn = resultifyP(original)

Calling resultifyP on a function returns a promise returning function similar to how util.callbackify works.

The original function is expected to be a promise returning function.

The returned function fn has the same arguments and returns a promise which does not reject and resolves to { err, data } which are the fulfilled and rejected value of the original promise.

const fn = resultifySync(original)

This function wraps a function that throws and returns { err, data } synchronously without returning a promise. Useful for JSON.parse

const parse = resultifySync(JSON.parse)

const { err, data } = parse('maybe good; maybe bad.')

No promises involved.

Installation

npm install resultify

Special Thanks

Special thanks goes to jkroso who was kind enough to give me the npm name resultify.

Check out some of his open source projects in Julia.

Contributors

  • Raynos

MIT Licenced.