Skip to content
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

Svelte doesn't subscribe to writables in :then blocks at the correct time #15211

Open
ForrestFire0 opened this issue Feb 5, 2025 · 2 comments
Labels
awaiting submitter needs a reproduction, or clarification

Comments

@ForrestFire0
Copy link

ForrestFire0 commented Feb 5, 2025

Describe the bug

I have a variable d which extends Writable and also has a property which is a promise (.ready). If I await on .ready and have {$d} in the markdown, it doesn't subscribe and unsubscribe when I expect it to.

See repro (don't worry it's only 45 lines should be comprehendible), but general concept is:

I expect to see what happens the first time:

(console shown below)

WE ARE UNSUBSCRIBING to 0:battery
new datastream on channel0:battery
Function is about to resolve, soon we should now be subscribing to 0:battery
THE THEN BLOCK IS RENDERING
WE ARE SUBSCRIBING to 0:battery

However when the button is pressed, we see the following additional messages:

new datastream on channel1:battery
WE ARE UNSUBSCRIBING to 0:battery
THE THEN BLOCK IS RENDERING
WE ARE SUBSCRIBING to 1:battery
Function is about to resolve, soon we should now be subscribing to 1:battery
THE THEN BLOCK IS RENDERING

First, I expect the reactive function to kick off, which happens. The function datastream() is run with correct arguments.
Then I expect the function to return, d to be re-assigned, and the then block to deconstruct itself. Which it does and 0:battery is unsubscribed from.
However, it seems the then block is then ran before re-checking the d.ready promise. It seems it subscribes to the new $d.

Questions:

  • Shouldn't the then block not be re-rendered when d is replaced before checking d.ready?
  • Why is $d subscribed to before d.ready settles?
  • Why doesn't $d become re-subscribed to when the then block re-renders and "THE THEN BLOCK IS RENDERING" is printed for the 2nd time?
  • Also - I note that $d is subscribed to even when "THE D BLOCK IS VISIBLE" is not visible.

Reproduction

https://svelte.dev/playground/7568c659fdff4847aad9433ff8070bed?version=5.19.7

Logs

See above. But:

about:srcdoc:299 running Svelte compiler version 5.19.7
about:srcdoc:299 WE ARE UNSUBSCRIBING to 2:battery
about:srcdoc:299 new datastream on channel0:battery
about:srcdoc:299 Function is about to resolve, soon we should now be subscribing to 0:battery
about:srcdoc:299 THE THEN BLOCK IS RENDERING
about:srcdoc:299 WE ARE SUBSCRIBING to 0:battery
about:srcdoc:299 new datastream on channel1:battery
about:srcdoc:299 WE ARE UNSUBSCRIBING to 0:battery
about:srcdoc:299 THE THEN BLOCK IS RENDERING
about:srcdoc:299 WE ARE SUBSCRIBING to 1:battery
about:srcdoc:299 Function is about to resolve, soon we should now be subscribing to 1:battery
about:srcdoc:299 THE THEN BLOCK IS RENDERING

System Info

In the REPL!

Severity

annoyance

@dummdidumm
Copy link
Member

This works as expected. Since #11989, the then block is kept around for the duration of one more microtask to account for immediately-resolved promises. During that time frame your store is updated, so it subscribes before switching to the pending block.

Is that causing any actual issues or is this more of a "why does it behave that way" question?

@dummdidumm dummdidumm added the awaiting submitter needs a reproduction, or clarification label Feb 5, 2025
@ForrestFire0
Copy link
Author

ForrestFire0 commented Feb 5, 2025

Thanks for your insight!
Definitely "why does it behave that way". Do you have any insight on why $d doesn't become re-subscribed to when the then block re-renders for the 2nd time?

What I expect:
promise changes
new $d is subscribed to (I see this)
(one microtask elapses)
$d is unsubscribed to (I don't see this)
(wait for d.ready to settle)
$d is subscribed to (I don't see this)

Why does $d not get unsubscribed and resubscribed to when the markdown doesn't have it showing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting submitter needs a reproduction, or clarification
Projects
None yet
Development

No branches or pull requests

2 participants