reflex-frp / reflex-dom

Web applications without callbacks or side-effects. Reflex-DOM brings the power of functional reactive programming (FRP) to the web. Build HTML and other Document Object Model (DOM) data with a pure functional interface.
https://reflex-frp.org
BSD 3-Clause "New" or "Revised" License
358 stars 145 forks source link

Catching errors #114

Open nh2 opened 7 years ago

nh2 commented 7 years ago

I'd like to perform an action when any part of my reflex-dom application throws an action.

I noticed that Control.Exception.handle at the top level doesn't seem to work, because apparently if an exception flies in widgetHold's second argument, it never bubbles up any more; instead only console.log(str); from function h$errorMsg(pat) { is invoked and my error message is printed to the developer console.

Is this what's supposed to happen?

Thanks!

ryantrinkle commented 7 years ago

Ah, this is quite a complex issue! I would expect Control.Exception.handle to catch issues happening during the initial widget build phase, but not anything happening in response to any Event other than getPostBuild firing. That's because events are processed in a separate thread - see https://github.com/reflex-frp/reflex-dom/blob/develop/src/Reflex/Dom/Internal.hs#L122

Do you have any ideas about how we should improve this?

3noch commented 7 years ago

It seems to me that FRP and exceptions do not mix well. Instead exceptions should be captured in the types.

ryantrinkle commented 7 years ago

@3noch Yes, definitely. My favorite approach, by far, to exceptions has been to avoid them completely. However, that doesn't mean we wouldn't be better off if we had a decent system for dealing with them when they (hopefully occasionally) do crop up!

nh2 commented 7 years ago

catch issues happening during the initial widget build phase, but not anything happening in response to any Event

Ah, right, that'll be it.

Do you have any ideas about how we should improve this?

@ryantrinkle for the beginning it would probably be enough (or at least very very helpful) if I can pass in an exception handler at the mainWidget level, so that I can catch it and log it.

avoid them completely

I'd like to, but when using lots of standard Hackage/base libraries, it's unavoidable that you trip over one that eventually uses a partial function / error inside. I'd like to be able to be notified when that happens in my users' browsers.

3noch commented 7 years ago

@ryantrinkle Ah yes I totally agree. In my limited use cases, I've always wrapped my IO code with catchAll or something similar and exposed the exception through performEvent in the types. That way the FRP model can still deal with the exception, but with normal FRP semantics instead of the imperative kind. If there are Reflex-DOM functions that are non-total, it might be best just to expose the exceptions via the types that way?

ryantrinkle commented 7 years ago

@3noch I don't believe there are any reflex-dom functions that are partial in their own right. However, there's always the possibility of a divide-by-zero or something like that cropping up in user code or by accident in reflex-dom.

One important thing to note is that reflex itself does not currently recover from exceptions during event propagation. Now, event propagation doesn't do IO, so it shouldn't be very likely to run into issues, but divide by zero is still possible.

nh2 commented 7 years ago

One important thing to note is that reflex itself does not currently recover from exceptions during event propagation.

@ryantrinkle If the exceptions bubbled up to mainWidget (thus terminating the FRP network), that would be compatible with this, wouldn't it? If I wanted to recover my app, I'd call mainWidget again.