ngrx polling to refresh data when subscribed

一曲冷凌霜 提交于 2020-01-03 16:49:29

问题


Context

I am using the following libraries in the relevant application: Angular 4.x, ngrx 4.x, rxjs 5.4.x

In my application I am able to get some data from a websocket but for some I have to hit a RESTful api. I am sharing the data between multiple components through ngrx. Right now I refetch the data based on events like create, update, and delete.

I don't expect much concurrent modification of the data but I do need a way to manually or automatically ensure that my client state matches the server. I would like to do optimistic updates that patch the client state rather than incurring the cost of doing a full data refresh on the relevant slice of state.

The RxJs Approach

If I wasn't using ngrx then I would probably just have a service that exposed an observable like the following that would cache the latest result of an api call and share it with all subscribes. It would update the result occasionally but only if it had subscribers.

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>

Problem

I'm not sure how I would mimic this same behavior with ngrx since ngrx handles the subscriptions to itself. In many ways it disconnects the subscription from the source. Here are some ideas I've mulled over:

  • Maybe there is a way that I could duck punch store.select but then I think that I would have to define explicit relationships between effects and state that are already defined in the reducers.
  • I could have each page/component register what it is interested in and track subscriptions that way but that is really just duplicating the subscriptions.
  • I could setup projections for each slice of state that would sit in front of ngrx and somehow trigger the related effect but that seems tricky and possibly convoluted.
  • Quit my job and sell pet rocks for a living.

Question

How can I pull data on an interval to update an ngrx store only when there are active subscriptions on the related slice of data?


回答1:


I don't think I understand what's going on 100%. But I think I would do something like this:

  • in my store, have some properties that track whether a piece of data is being watched (boolean)
  • when a component loads that watches that data, dispatch an event setting that value to true
  • use ngOnDestroy to set the value to false when the component is no longer there
  • have an ngrx effect that watches if that value changes. If the value changes to true, start fetching data from the server, and when it gets a response, dispatch an event to update the data in the store, and keep doing that at a certain interval. Keep the return value of your setInterval or timer in a variable that can be accessed elsewhere, maybe as a property of the class.
  • if the value changes to false, a different ngrx effect is listening for that action, will grab that variable holding the timer/interval, and clear it/unsubscribe. Might be able to compose these together with takeUntil


来源:https://stackoverflow.com/questions/47597518/ngrx-polling-to-refresh-data-when-subscribed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!