Подпишитесь на документ с помощью Svelte / RxJs / RxFire. Как мне обновить подписку
Я использую производное хранилище в приведенном ниже коде. Это выглядит странной конструкцией, потому что я использую производную конструкцию только для динамической зависимости $session и для получения normData. Но не с нормой $. Я использую $norm только один раз, чтобы запустить производное хранилище.
Тем не менее, похоже, все работает нормально. Но я должен продлить подписку, если $session изменится. Можно ли обновить подписку RxFire / RxJs без предварительного отказа от подписки?
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();
});
Обновление: я могу использовать параметры set и return производного хранилища, чтобы изменить $norm в реальном хранилище $norm Svelte. Код ниже в моем собственном ответе.
Но реальный вопрос: могу ли я обновить подписку. Сменить подписку без отписки?
2 ответа
У меня уже был ответ, но я его не осознавал.
Ниже производного кода магазина с параметрами set () и return ().
Когда сеанс изменяется, return () автоматически отписывается.
Так что все еще отписываюсь от подписки, а не обновляю... но это хорошо. Приятно!
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.closed) {
normSubscription.unsubscribe();
}
});
Производное хранилище документов API:
Получает магазин от одного или нескольких других магазинов. Каждый раз, когда эти зависимости меняются (например, $session), выполняется обратный вызов.
Если вы "возвращаете функцию" из обратного вызова, она будет вызываться (перед обратным вызовом), когда а) обратный вызов запускается снова (из-за изменения зависимости) или б)...
Хорошо, примерно то, что вы пытаетесь описать здесь.
Фактически вы можете использовать реактивное объявление для выполнения кода при изменении переменной / хранилища.
В этом случае следует выполнить метод повторной подписки:
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();
});
Ключевым моментом здесь является то, что при компиляции Svelte знает, что блок зависит от $session
, поэтому он будет повторно выполнять блок кода всякий раз, когда $session
изменилось.
Если вы захотите преобразовать его в другую функцию, вы должны убедиться, что Svelte знает, что функция зависит от $session
, то есть:
$: resubscribe_norm($session);
Здесь Svelte может сказать, что если $session
поменял, нужно позвонить resubscribe_norm
еще раз.