【问题标题】:Subscribe to a doc using Svelte / RxJs / RxFire. How can I update the subscription使用 Svelte / RxJs / RxFire 订阅文档。如何更新订阅
【发布时间】:2019-11-12 00:54:13
【问题描述】:

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

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

【问题讨论】:

  • 如果我误解了您的问题,请纠正我,您想在session 更改时重新订阅normDocRef
  • 文档的名称包含年份,例如 Foo2010..Foo2019。因此,当我更改会话年份时,我想更新订阅。

标签: rxjs svelte derived rxfire


【解决方案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 docs派生商店:

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

如果你从回调中“返回一个函数”,它将在 a) 回调再次运行时被调用(在回调之前)(因为依赖项发生了变化) , 或 b) ...

【讨论】:

    【解决方案2】:

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

    当变量/存储发生变化时,您实际上可以使用reactive declaration 来执行代码。

    本例是执行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

    【讨论】:

    • 这不是问题。派生存储依赖于会话,并且会在会话更改时更新订阅。它在我展示的代码中运行良好。这里没有问题。但是是否可以更新订阅(查询)。在不取消订阅/订阅的情况下切换到另一个文档。
    • 感谢您的回复。我也更新了这个问题。不清楚。
    • 不知道你在找什么,你是否可以在不取消订阅的情况下更新订阅,这取决于db.doc,这不是来自苗条吗?
    • 也许你可以被动地声明$: normDocRef = db.doc(`uploads/${$session.a_id}_${$session.year}`),然后派生norm而不是$session。所以你也可以根据需要手动更改normDocRef
    猜你喜欢
    • 1970-01-01
    • 2020-07-27
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多