问题
I use a derived store in the code below. It feels like a strange construct because I only use the derived construct for the dynamic $session dependency and to get the normData. But not with $norm. I use $norm only once to kick off the derived store.
Nevertheless it seem to work fine. But I have to renew the subscription if the $session changes. Is it possible to update the RxFire / RxJs subscription without unsubscribing first?
let normDocRef = null;
let normData = null;
let normSubscription = null;
const norm = derived(
session,
$session => {
normDocRef = db.doc(`uploads/${$session.a_id}_${$session.year}`);
// renew the subscription if $session changes
if (normSubscription)
normSubscription.unsubscribe();
normSubscription = doc(normDocRef).subscribe(snapshot => {
if (snapshot.exists) {
normData = snapshot.data();
} else {
normData = null;
};
});
},
);
$norm; // kick off the derived store to monitor $session
// show the data and updates
$: console.log(normData);
onDestroy(() => {
if (normSubscription) normSubscription.unsubscribe();
});
Update: I can use the set and return options of the derived store to change $norm in a real $norm Svelte store. Code below in my own answer.
But the real question is: Can I update a subscription. Change the subscription without the unsubscribe?
回答1:
I already had the answer, but did not realize it.
Below the derived store code with the set() and return() options.
When the session changes the return() will unsubscribe automatically.
So still an unsubscribe and not an update ... but this feels good. Nice!
let normDocRef = null;
let normSubscription = null
const norm = derived(
session,
($session, set) => {
normDocRef = db.doc(`uploads/${$session.a_id}_${$session.year}`);
normSubscription = doc(normDocRef).subscribe(snapshot => {
if (snapshot.exists) {
set(snapshot.data());
} else {
set({}); // clear
};
});
return () => {
normSubscription.unsubscribe();
};
}, {} // initial value
);
$: console.log('$norm', $norm); // Now it is a real store
onDestroy(() => {
if (normSubscription) {
normSubscription.unsubscribe();
}
});
回答2:
Ok, roughly get what you trying to describe over here.
You can actually use the reactive declaration to execute code when a variable / store changed.
In this case is to execute the resubscribe method:
let normDocRef = null;
let normData = null;
let normSubscription = null;
$: {
normDocRef = db.doc(`uploads/${$session.a_id}_${$session.year}`);
// renew the subscription if $session changes
if (normSubscription) {
normSubscription.unsubscribe();
normSubscription = doc(normDocRef).subscribe(snapshot => {
if (snapshot.exists) {
normData = snapshot.data();
} else {
normData = null;
};
});
}
}
onDestroy(() => {
if (normSubscription) normSubscription.unsubscribe();
});
The key here, is that when compiling this, Svelte knows that the block is depending on $session
, so it will re-execute the code block whenever $session
changed.
Should you want to refactor it out into another function, you need to make sure that Svelte knows that function depends on $session
, ie:
$: resubscribe_norm($session);
Here, Svelte can tell that, if $session
changed, need to call resubscribe_norm
again.
来源:https://stackoverflow.com/questions/58810550/subscribe-to-a-doc-using-svelte-rxjs-rxfire-how-can-i-update-the-subscripti