question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Error handling in flyd (Proposal)

See original GitHub issue

I want to propose we implement the bifunctor spec to facilitate error handling.

If we look at the synchronisation quadrant

Flyd belongs in the asynchronous multi-value category (observable).

Looking at the Single value asynchronous landscape in functional fantasy-land compliant javascript one of the outstanding libraries is Fluture

They implement Bifunctor, Monad and ChainRec.

I would like to propose that flyd does the same.

This will allow users of flyd to operate with the same interface on single-value and multi-value async data.

There are two methods of note WRT error handling:

bimap :: (Bifunctor f) => f a b ~> (a -> c) -> (b -> d) -> f c d fold :: (Bifunctor f) => f a b ~> (a -> c) -> (b -> c) -> f c d

A contrived example using Fluture

const example = Future.encaseP(fetch)('/example.json')
  .chain(res => future.encaseP(()=> res.json())())
  .bimap(tap(success => console.log(success)), tap(error => console.error(error)))
  .fold(Either.Right, Either.Left)

equivalent code in flyd if we go this route:

const example = flyd.fromPromise(fetch('./example.json'))
  .chain(res => flyd.fromPromise(res.json()))
  .bimap(tap(success => console.log(success)), tap(error => console.error(error)))
  .fold(Either.Right, Either.Left)

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
nordfjordcommented, Oct 14, 2018

I’ve tested this out a bit using my own codebase, but rather than making flyd a bifunctor I’ve just been hosting an either inside the stream

const promiseToEitherStream = <T>(promise: Promise<T>) => {
  const s = stream<Either<Error, T>>();
  promise
    .then(val => s(Right(val)))
    .catch(err => s(Left(err))
    .finally(()=> s.end(true));
  return s;
}

This has actually been quite sufficient for my error handling use cases.

I’m closing this issue because of that.

0reactions
nordfjordcommented, Nov 15, 2018

Hey @StreetStrider

I think we can agree on a few things.

  1. Flyd should not swallow user errors
  2. Flyd should not break on user errors

The question is then how do we solve both.

My thesis in this issue was that we could make Flyd a bifunctor to better model the same flows we see in libraries like Fluture.

However, I also really like composing smaller things together to make larger things. I think if we can get away with just supporting those two use cases (not swallowing errors, and not breaking on errors) we allow the end user to pick their error handling strategy. An example would be using Either.

e.g. imagine:

const s = stream();
const errorable = s.map((val)=> {
  if (Math.random() >= .5) throw new Error('hahahhaa');
  return val * 2;
})

s(1)(2)(3)(4)(5);

I imagine that it’s much superior for the user to be able to do something like:

const s = stream();
const errorable = s.map(Either.try((val)=> {
  if (Math.random() >= .5) throw new Error('hahahhaa');
  return val * 2;
}))
.map(console.log);

s(1)(2)(3)(4)(5);

A solution like the above

  1. Allows us to keep flyd minimal
  2. Allows users to decide on how to handle errors.

But that is predicated on us not violating the two use cases.

You could also implement something like:

const safeMap = curry((fn, s)=> combine((s, self)=> {
  const value = Either.try(fn)(s());
  value.map(self).leftMap(self.end);
}, [s]));

const s = stream();
const errorable = s.pipe(safeMap((val)=> {
  if (Math.random() >= .5) throw new Error('hahaha');
  return val * 2;
}));
s(1)(2)(3)(4)(5);

if you want your stream to end on errors.

With the example above I think we might want to allow values other than true in end streams.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error Handling — Problem Overview
Open returning the name of the file being opened. Returning the error unmodified produces a failure without any information about the sequence ......
Read more >
A Proposal for Error Handling - tratt.net
Error checking is where functions return a code denoting success or, otherwise, an error; callers check the error code and either ignore it, ......
Read more >
proposal: Go 2: error handling: try statement with handler
Say you would want to debug a code and see why error x appears somewhere. You identify that piece of code where it...
Read more >
Learn best practices for debugging and error handling in an ...
To handle chaincode to chaincode communication errors, unique error codes can be propagated by the caller chaincode and the client application ...
Read more >
Proposal: XCTest Support for Swift Error Handling - Discussion
As an example, a vending machine object that has had insufficient funds deposited may throw an error if asked to vend an item....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found