-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error handling in flyd (Proposal) #171
Comments
@nordfjord where does |
Any Either will do, e.g. Or anything really. Pick your poison :) |
I think the most important notion in this proposal is the fact that it allows seamless interop between fluture and flyd. This means that if at any point you realise that your future code really needs to handle multiple values the recourse is as simple as replacing I think the error handling capabilities it provides are a nice bonus though. |
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. |
Got some thoughts today. Barely ideas, not a strong concept.
|
Hey @StreetStrider I think we can agree on a few things.
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 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
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 |
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
equivalent code in flyd if we go this route:
The text was updated successfully, but these errors were encountered: