DEV Community

Cover image for JavaScript error handling with better `dx`
Jason Tu
Jason Tu

Posted on

JavaScript error handling with better `dx`

JavaScript expects you to handle errors with try...catch, but the syntax is somewhat inconvenient:

1. You have to declare result variables separately from your function calls.

const userInput = 'fail'

let json
try {
  json = JSON.parse(userInput)
} catch (err) {
  console.error(err.stack)
}

// Do something with `json`...

Since we declare json separately, we can't declare json as a const binding.

2. try...catch promotes catch-all error handling.

try {
  // A bunch of stuff happens...
  // ...
  // ...
} catch (err) {
  console.log('welp')
  console.error(err.stack)
}

You might want to handle errors in a more fine-grained way. But then you run into the verbosity of problem 1.

Enter dx

dx is a micro utility (it's just a few lines) that addresses the two pain points above.

import { dx } from '@nucleartide/dx'

const [res, err] = dx(JSON.parse)('invalid json')
if (err) {
  console.error(err.stack)
}

It allows you to place your declaration and function call on the same line. And it promotes a granular, per-function error handling style.

It also works with async functions:

import { dx } from '@nucleartide/dx'

function asyncHello(name) {
  return Promise.reject(`hello ${name}`)
}

;(async () => {
  const [res, err] = await dx(asyncHello)('jesse')
  if (err) {
    console.error(err.stack)
  }
})

Convinced?

Try it out and lemme know what you think! Also feel free to check out the source.

npm install @nucleartide/dx

Discussion (12)

Collapse
joelnet profile image
JavaScript Joel

This is kind of like a poor man's Either!

Collapse
puritanic profile image
Darkø Tasevski

What is this abomination:

;(async () => {

😱

Collapse
joelnet profile image
JavaScript Joel

You cannot use async/await in the global scope. By wrapping your code in an async function, this trick will let you use await.

Collapse
puritanic profile image
Darkø Tasevski

Are you sure about that? I know that you can't use await without async but if I remember correctly I've used async function in top-level scope a few times 🤔

Anyway, I was thinking about that semicolon at the beginning which purpose is to guard against AST, confusing and ugly syntax IMO.

Thread Thread
joelnet profile image
JavaScript Joel

Are you sure about that?

You can test by pasting an await command into the browser console.

Anyway, I was thinking about that semicolon at the beginning

Ahh ya. It's just a guard.

Collapse
joelnet profile image
JavaScript Joel

Where does the dx name come from? What does it mean?

Collapse
nucleartide profile image
Jason Tu Author

It could mean a lot of things? Developer Experience, De-Exception, Derivative, Ducks, etc.

I like the first 2 definitions best. Besides that, it's just short and convenient to type.

Collapse
tux0r profile image
tux0r

But then you run into the verbosity of problem 1.

Hmm, wouldn't importing a complete NPM module add even more verbosity?

Collapse
nucleartide profile image
Jason Tu Author

You could always copy the module into your project! npm is just there as a convenience.

Collapse
tux0r profile image
tux0r

It still has 18 additional ("verbose") lines. :-)

Collapse
yorodm profile image
Yoandy Rodriguez Martinez

You Javascript people need Monads, or some decent metaprogramming, or macros, whatever make you stop creating libraries from every single useful snippet of code out there

Collapse
mojtabamarashee profile image
seyed mojtaba marashi

good idea