使用 Svelte / RxJs / RxFire 订阅文档。如何更新订阅

Subscribe to a doc using Svelte / RxJs / RxFire. How can I update the subscription

我在下面的代码中使用了派生商店。这感觉像是一个奇怪的构造,因为我只使用派生构造来获取动态 $session 依赖项并获取 normData。但不是 $norm。我只使用 $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();
}); 

Update:我可以使用派生商店的 set 和 return 选项来更改真正的 $norm Svelte 商店中的 $norm。下面的代码在我自己的回答中。

但真正的问题是:我可以更新订阅吗?更改订阅而不取消订阅?

好的,大致了解您要在此处描述的内容。

您实际上可以使用 reactive declaration 在变量/存储更改时执行代码。

本例是执行重新订阅方法:

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

我已经有了答案,只是没有意识到。

在带有 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 docs 衍生商店:

从一个或多个其他商店派生商店。每当这些依赖项发生变化时(如 $session),回调就会运行。

如果您从回调中 "return a function",它将被调用(在回调之前)当 a) 回调再次运行时(因为依赖关系改变), 或 b) ...