1

我在下面的代码中使用了派生商店。这感觉像是一个奇怪的构造,因为我只将派生构造用于动态 $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();
}); 

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

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

4

2 回答 2

1

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

在带有 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),回调就会运行。

如果您从回调中“返回一个函数”,它将在 a) 回调再次运行(因为依赖项已更改)或 b)时被调用(在回调之前)...

于 2019-11-12T10:16:11.133 回答
0

好的,在这里大致了解您要描述的内容。

当变量/存储发生变化时,您实际上可以使用响应式声明来执行代码。

本例是执行resubscribe方法:

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再次调用。

于 2019-11-12T07:44:08.183 回答