How to onCleanup an async resource from createResource?
or
or
or something else entirely?
I need to cleanup the connection when the resource re-fetches, and when the whole subtree is disposed of. If I don't the browser leaks the resource and eventually crashes.
41 Replies
i would have done 1. but I wasn't aware of this second argument in the fetcher
from the docs it says
The value property tells you the previously fetched value.so ig you should not use
onCleanup
then:
yeah I can confirm that option 2 definitely doesn't work
it's hard following memory leaks, but option 1 results in an 8mb process, option 2 results in 16gb process
yeah I can confirm that option 2 definitely doesn't work… or there is something strange going on in
tryOnCleanup
This PoC works as intended:
https://playground.solidjs.com/anonymous/67705400-1213-473b-8ca9-e949723b7446
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
That PoC leaks memory when used with
onCleanup
, for example:
https://playground.solidjs.com/anonymous/96d8f185-c590-4ae6-acfc-6c53fd4f9dc3
note especially that destroying the whole component fails to cleanup the last value in handle2
and otherwise retains two handlesnotice how peer and my example do not have the cleanup in an
onCleanup
it's probably still not the way for u to go, bc our examples only cleanup when the resource is re-triggered, not when the resource itself is cleaned up.What is motivating you to use
onCleanup
in that particular manner? I'm not sure it was designed to be used that way.
I see disposing on rerun and on component disposal as two separate concerns. onCleanup
is appropriate for the latter …
https://playground.solidjs.com/anonymous/57135dd8-578d-41a8-b13a-6b8c85e66863Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
I see disposing on rerun and on component disposal as two separate concerns.mechanically these are the same tho? both is an owner that cleans up
The first is “I'm done with this asset because I'm getting another one”. The other is “I'm done with the context that is using the asset”.
i am not talking semantically
but mechanically
I'm talking when vs. how.
I need the resource created to be destroyed when no longer necessary. And due to browser issues I can't rely on "garbage collection" to deal with it, the tab just crashes after a bit without manually cleaning up
when the resource goes "out of scope" either due to the component that owns the resource being removed or the resource being refetched, I must perform the cleanup operation or the browser leaks the resource
using
setTimeout
doesn't work because the resource will likely be used after an arbitrary period of time, the only time that I can cleanup the resource is when its owner gets disposed, or the value gets refetchedThe issue with
onCleanup
is that you set cleanup for the next rerun. But in your option 2 input.value
is from the previous run; so your cleanup runs “one behind”. Option 1 is only OK if you synchronously dispose otherwise there could be a racing condition on var handle
.
That's why I don't like onCleanup
in there.yeah. But what is the alternative to
onCleanup
? I do realize that if the refetch happens inbetween registering the onCleanup
and the await resolving, then the resource gets lostno you are right, for option 2. you should not use
onCleanup
option 1. is probably the way to go
because otherwise you don't cleanup when the resource cleans uphttps://playground.solidjs.com/anonymous/57135dd8-578d-41a8-b13a-6b8c85e66863
Use
onCleanup
on the component level to dispose of the current instance. Within the rerun dispose of the previous instance directly.Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
i think this is valid too:
That's an option, it's just not scheduling the dispose after resource is no longer accessible
the
await
allows other code to run, before the promise resolves. The resource could be re-fetched or disposed of in that inbetween space, causing the onCleanup
to run before resource
gets assignedThis is what you want
no that won't work
that onCleanup never runs, since its outside of
Owner =
contextbecause the onCleanup would be behind the async boundary
not following there
ooo
now i see
yeah. I haven't actually seen that behavior in the wild, but it's probably only a matter of time
ok ok now i understand the full problem
ye i guess this is actually not a bad approach then
ugly but it does cover the case
stuff like
you are also not sure if the promise is resolved before the resource is called again
you have to do it inside the resource
Why use
var
(instead of let
)?i copied OP
So there is nothing wrong with this?
no it should probably be this
because of this
I think that does bad things to suspense, right? need to check the status first
or it'll block loading of the whole component
also true
Sounds like you want to delay disposal
oof, actually, on refetch
getOwner()
returns null, so no solution involving onCleanup
in the body of the resource fetcher is legal
odd that the dev-mode warnings aren't enabled in the playgroundI ran into that recently
https://discord.com/channels/722131463138705510/1331331792279568454/1331706656786223205
ah that's helpful, thanks
that's surprising!
https://playground.solidjs.com/anonymous/1a217951-b559-48ef-b603-8ed454c5b027 yeah, I think this is probably a bug
https://github.com/solidjs/solid/issues/2428
found a better solution (aside from the refetch bug)
That can still clean up before the next
task
has finished its await
.that's true, I need to check that createResource discards the result of the promise, if it's already refetching
I assumed it discarded it, because I can't imagine otherwise
it discards them,
doesn't report observing any intermediate values produced by fetches that were refetched while running
I'm pretty sure this is safe
I guess it's OK if you don't use
latest
.https://playground.solidjs.com/anonymous/3cdd6c45-18b2-432f-9663-2f6e1661562b is the playground I'm working on
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
I see what you mean about latest, I'm not sure that's fixable given the api createResource offers
I wonder if “non-nullable”
createAsync
for 2.0 is going to have an impact.
With 1.x createAsync
reverts to undefined
during rerun/refetch; my suspicion is that with 2.x it behaves more like a stale-while-revalidate, i.e. the new pending promise is still thrown to trigger suspense but the stale value is still available on the accessor.