【问题标题】:ngrx polling to refresh data when subscribed订阅时,ngrx 轮询刷新数据
【发布时间】:2018-05-15 19:15:50
【问题描述】:

上下文

我在相关应用程序中使用以下库:Angular 4.x、ngrx 4.x、rxjs 5.4.x

在我的应用程序中,我能够从 websocket 获取一些数据,但对于一些我必须使用 RESTful api。我正在通过 ngrx 在多个组件之间共享数据。现在我根据创建、更新和删除等事件重新获取数据。

我不希望对数据进行太多并发修改,但我确实需要一种手动或自动确保我的客户端状态与服务器匹配的方法。我想做乐观的更新来修补客户端状态,而不是产生对相关状态片进行完整数据刷新的成本。

RxJs 方法

如果我不使用ngrx,那么我可能只是有一个服务,它暴露了一个如下所示的可观察对象,它将缓存api调用的最新结果并与所有订阅者共享。它会偶尔更新结果,但前提是它有订阅者。

const interval = 1000;
let counter = 0;

// setup a timer that executes immediately and on a timer
let call = Rx.Observable.timer(0, interval)
  // make the fake async call
  .switchMap(() => Rx.Observable.of(counter++).delay(100))
  .do(x => console.log('call', x))
  // cache latest value and share the value with all subscribers
  .publishReplay(1, interval)
  // only connect (aka make the call) if there are more than 1 subscribers
  .refCount();

// convenience method for simulation
function subscribe(name, take) {
  call.take(take).subscribe(
    x => { console.log(name, x); },
    null,
    () => { console.log(`${name} completed`) }
  );
}

// observers
subscribe('first', 1);
subscribe('second', 2);
window.setTimeout(() => {
  subscribe('third', 3);
}, 3500);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.min.js"></script>

问题

我不确定如何使用 ngrx 模拟相同的行为,因为 ngrx 会处理对自身的订阅。在许多方面,它断开了订阅与源的连接。以下是我考虑过的一些想法:

  • 也许有一种方法可以让我回避拳头store.select,但我认为我必须明确定义效果和状态之间的关系,这些关系已经在 reducer 中定义。
  • 我可以让每个页面/组件注册它感兴趣的内容并以这种方式跟踪订阅,但这实际上只是复制订阅。
  • 我可以为位于 ngrx 前面的每个状态切片设置投影,并以某种方式触发相关效果,但这似乎很棘手,并且可能令人费解。
  • 辞掉工作,以卖宠物石为生。

问题

只有在相关数据片上有活动订阅时,我才能按时间间隔提取数据以更新 ngrx 存储?

【问题讨论】:

    标签: javascript angular rxjs ngrx


    【解决方案1】:

    我不认为我 100% 了解发生了什么。但我想我会做这样的事情:

    • 在我的商店中,有一些属性可以跟踪是否正在监视一条数据(布尔值)
    • 当组件加载监视该数据时,调度一个将该值设置为 true 的事件
    • 当组件不再存在时,使用 ngOnDestroy 将值设置为 false
    • 具有一个ngrx 效果,可以观察该值是否发生变化。如果该值更改为 true,则开始从服务器获取数据,当它收到响应时,调度一个事件以更新存储中的数据,并以一定的时间间隔继续执行此操作。将 setInterval 或计时器的返回值保存在可以在其他地方访问的变量中,可能作为类的属性。
    • 如果值更改为 false,则另一个 ngrx 效果正在侦听该操作,将获取保存计时器/间隔的变量,并清除它/取消订阅。或许可以将这些与 takeUntil 组合在一起

    【讨论】:

    • 我会做的一个改变是它不是一个布尔值,而是一个列表,所以如果多个组件正在监听,那么如果一个组件离开它不会停止为另一个组件更新。所以一个列表在改变后检查它是否为空
    • 如果您不想为每个订阅者生成唯一标识符,也可以使用计数器。
    • 这类似于我在“问题”下的第二个选项。如果可能,我想避免重复跟踪订阅。重复可能会导致一致性问题。不过,关于如何实施的好建议!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多