Sitemap

Asynchronous Functional Error Handling with Javascript

4 min readSep 14, 2019

Oh Async/Await in javascript is so cool. Sure :

Async/await makes it finally possible to handle both synchronous and asynchronous errors with the same construct, good old try/catch

Yep. The good old try/catch. Yes this plague, rotting imperative code-bases since ever. Fortunately functional community had a better idea for error handling, and that’s called Either monad (aka Result) . This article is all about using the same good functional pattern of Either along with Promises to deal with asynchronicity without deviating from the functional coding styles.

we aim at being able to write something like the following:

instead of this :

const makeRequest = async () => {
try {
// this parse may fail
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}

}

The only problem is to create this magic toEither function on Promises. We want to be able to use the Interface of the Either but only after we know if the promise was resolved or rejected, then execute the computations. First we will just create the cata method and then go to the map and bind.

if you are unfamiliar with either you can take a look at this article

you can also check the example usages of one of my favourite libraries called pratica (its called result in this lib)if you are unfamiliar with the concept.

cata implementation

the idea behind cata is to return a single value out of a data structure.

using cata we syntactically write this :

.cata({                         
ok: response=> console.log(response),
error: err=> console.log("error:" + err) });

instead of this:

fetch( )  
.then(response => console.log(response))
.catch(err => console.log(err))

Its so simple but callbacks are confusing to follow. You can try to design this by yourself and have a feel about the mechanics.

Implementing Map

Cata is easy, but we want to be able to use map too. And now comes the hard part. Delay the mapping until the promise has been fulfilled and we know which path should we follow. There is this idea called coyoneda that does just that. I am not going to get into the theory but i will just give a simple example to get the mechanics .

We keep the function composition as an argument and every time we use map , we compose and store the composition.

Coyo(value, x => f(accf(x)))

After we call lower we apply the value to the overall function composition that we have accumulated.Now we can use coyoneda to delay execution.

The map of Either only maps the resolved successful part and not the faulty part.

Thats why in cata we only lower ( execute the computations of Coyoneda ) and apply the mapping function for the ok part. For the error we just return the error.

this.cata = alg => actions(x => alg.ok(this.lower(x)), alg.error);

Implementing Bind

we also want to be able to chain computations with other Either to make it a monad. We can implement that by knowing that only when the successful path is completed we combine the right sides of the two Eithers.

can you figure out the updated bind implementation ??

now we can write stuff like this :

where we combine promises in a functional syntax style, using either, without going to the nested try/catch thing. If any of those fetch fail then the final result would contain the error.

you can try use the npm package

https://leanpub.com/c/functionaljswithcatscourse
functional programming in Javascript in Amazon

--

--

Dimitris Papadimitriou
Dimitris Papadimitriou

No responses yet