Effects not running after a unhandled promise rejection event
When an unhandled error event occurs (e.g. by throwing
new Error()
), the ErrorBoundary
is catching the error.
When an unhandled promise rejection occurs, the UI/JSX is being updated, I display the state of the resource in the JSX, and it switches from pending
to errored
, but the createEffect
functions are not running:
When displaying {userResource.state}
from the JSX, it prints pending
and then updates to errored
because there was a promise rejection. It reacts.
However the createEffect
above only logs pending
once and will not log errored
, while the JSX did react/get updated.
26 Replies
The problem is that I throw in some
createEffect
, which seems to break the subsequent createEffect
s.
Commented on the issue https://github.com/solidjs/solid/issues/1744#issuecomment-1576305964Throwing errors in effects certainly doesn't look like a good idea to me
I see what's the goal - to have the error bubble up to the global listeners, but that's not the way to do it.
There are two options here - either don't use createResource, or expose the global event listener functions, and call them inside the effect as a workaround. Or use the ErrorBoundary...
I could indeed reuse some function. Now I call
setTimeout(() => { throw e }, 0)
which has been working fine to make the error bubble up.You are opting out of the tracking system with that setTimeout
I would strongly advise that you rethink the strategy of bubbling exceptions to the top just to log them.
yes but I don't need the tracking system, I want to throw outside of the synchronous execution (so that asynchronously the global listener sends the error to some reporting tool). It has been working fine consistently.
Would you mind sharing me why that could be considered bad code for this case?
It bubbles up through all the layers of your code, and a lot of them will break on an unexpected error. I would assume that React and many others will do the same - the rendering system would just crash.
with the setTimeout? Don't I get outside of the synchronous execution and so, not interfering with Solid "work"?
You are opting out of the system
ah but wait, I still handle the error in addition to making the error bubbling up
That's even worse...
Rethrowing the error just for the sake of logging
I would advise a different approach for that - since the error is already handled, just log the exception in a different way - you have context in solid, or you could export global logging functions.
yeah I could simply use some global function to log the error. I think your argument if I get you right, is that the rethrow with
setTimeout
is a little hacky. I don't think it interferes with Solid's execution so it will consistently reach the global listener without interfering with the reactive system, however it's too hacky?
I got your thoughts right?It's not too hacky, it's just .... inefficient.
It will work in this case, however, it will require circumventing each and every one of the code layers which do not like unhandled exceptions - which I assume are a majority.
I would rather just handle the error where it occurs and use a global logger
ok there's just one core thing I don't get, is how some code layer could intercept an unhandled exception thrown from a settimeout
It could not
But you are scheduling a microtask, and rethrowing an exception to probably just log an error
And I don't like that at all
haha I see, the global logger is a nice idea anyways, thank you so much for the help as always!<3
The global logger is something that permiates through all of your code.
Not sure if it's such a nice idea
But there are ways to implement it to not require bubbling up of exceptions
And I suggest those
However, to each his own
learned a new word too:D but apparently spelled permeates
Not a native speaker, so forgive my english
same
In the class based world, you would either have to have a logger as a dependency injected in the constructor to be clean
generally speaking in JavaScript, what would be the disadvantage of that in your opinion?
Because with the IDE search functions you can find calls easily.
As long as it is used in application code (not some generic system where we'd rely more on dependency injection), I can't really think of a disadvantage. And I can imagine a lot devs importing global functions like utility functions throughout the app.
It's some form of bad inheritance it's true. but I can't find the arguments right now against it
It's inefficient
It's a global logger implementation attached to the window
Which requires the exception to bubble up
Why don't you use a singleton and log the error where it occurs?
the logger is just an interface
I'm talking about the solution of exporting a global logger function and what you said:
The global logger is something that permiates through all of your code. Not sure if it's such a nice ideaIn my code I'd have: and I could export this
handleError
and import that function instead of rethrowingTrue
You can also put those in a context
But I like plain export more
but it's funny that on the server I'd be shocked if I see something like this. We'd go for dependency injection.
these two should be there just a last safety line
And then all your classes would depend on a logger
On which they do not really depend at all