New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

async-unwrap

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

async-unwrap

Simple tool to avoid try-catch blocks

latest
Source
npmnpm
Version
1.1.0
Version published
Weekly downloads
6
-45.45%
Maintainers
1
Weekly downloads
 
Created
Source

Async-await can help you write some amazing-looking and very readable code, but if you're anything like me, you probably hate burying it into try-catch blocks. With async-unwrap, you can go from this:

async () => {
  try {
    await someAsyncOperation()
  } catch (err) {
    doSomething(err)
  }
}

to this:

async () => {
  const [err, result] = await someAsyncOperation()[unwrap]
  if (err) return doSomething(err)
}

But how?

First, you need to say the magic word:

const unwrap = require('async-unwrap')
// or if the above is way too old for you:
import unwrap from 'async-unwrap'

This gives you a symbol that's attached to the prototype of every promise (or other thenable), which turns that promise into another one. The "unwrapped" promise will resolve to a tuple two-element array of [null, result] if the base promise is resolved and [err, null] if it's rejected. This allows you to handle your errors in a slightly different way, without breaking the block scope.

If you're using multiple async calls in a function, I'd recommend structuring your code in the following way:

async () => {
  const [firstError, firstResult] = await firstOperation()[unwrap]
  if (firstError) throw firstError // we'll handle it on a higher level

  const [secondError, secondResult] = await secondOperation(firstResult)[unwrap]
  if (secondError) throw sanitize(secondError) // sometimes you'll need some special treatment

  return secondResult
}

Exercise to the reader: try writing that without nested try-catch blocks or falling back to let.

Local offensive

Before you ask, yes, that does modify global variables, specifically Object.prototype, which is actually the variable you should have the most caution with modifying. async-unwrap uses a symbol to define a non-enumerable getter, minimizing the surface for errors (it's practically invisible in normal usage), but in some exotic cases you might still run into problems with that. If you'd like to not take that chance, there is a "function" variant of the library:

import unwrap from 'async-unwrap/func'

async () => {
  const [err, result] = await unwrap(someAsyncOperation())
  if (err) return doSomething(err)
}

Why is this not the default? Well, frankly because I think it's ugly, but to each their own. You can use the function variant if you'd like to, no hard feelings.

Compatibility

Everything, theoretically. The library binds to all objects and simply checks for a then() method, which is the JS spec's way of deciding if something is a promise. This should enable it to work seamlessly with custom promise implementations. If you still run into any compatibility issues, please submit a bug report.

Contributing

Pull requests are welcome. As always, be respectful towards each other and maybe run or create tests, as appropriate. It's on npm test, as usual.

async-unwrap is available under the MIT license.

Keywords

async

FAQs

Package last updated on 15 Feb 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts