简体   繁体   中英

RxJS Register event sources and buffer events dynamically

I'm currently trying to get a Register/Subscribe system to work with RxJs.

The situation is that I have component A with several sub components A1, A2, A3, ... The amount has to be dynamic. What I want to do now is that whenever an event I will call "somethingChanged" occurs (which is already distributed through an Observable) all sub components A1, ... will do some processing and then return some information (a state) as an event I'll call newStates to the parent action A probably using another observable. For this to work the sub components first have to register themselves to the "event manager" as children of A so that these events can be processed accordingly.

First idea

My first idea for this was to use a bufferCount on the newStates observable with the count being the amount of registered sub components. The problem is that the sub component registering and the parent component subscribing to the newStates observable is happening at almost the same time, the parent even being slightly faster which means the amountSub is usually 0 which breaks this attempt.

registerSubComponent() {
  amountSub++;
}

getParentObservable() {
  return newStates.bufferCount(amountSub).mergeMap();
}

Second idea

The second attempt was to use the somethingChanged Event and use that to initialize a takeLast to get the last items when they should be thrown. The problem is again as i will run into race condition as sub components take longer to throw their newStates events meaning I'll get old values.

registerSubComponent() {
  amountSub++;
}

getParentObservable() {
  return somethingChanged.map(() => newStates.takeLast(amountSub);
}

Third idea

So currently my only idea would be to catch the newStates event in the event manager, store the states in an array and check everytime if all registered components send them by looking at the array length. When all states are in i could then send the saved states and reset the array.

registerSubComponent() {
  amountSub++;

}

getParentObservable() {
  return newParentObservable;
}

newStates.subscribe(state => {
  savedStates.push(state);
  if(savedStates.length == amountSub) {
    newParentObservable.next(savedStates);
    savedStates = [];
  }
});

Is this the only way or am I missing something so it could be done easier/with observables?

Btw: This is all pseudo code as my actual code also has to support multiple parent components in one manager making it cumbersome to read through.

It sounds like you want change detection up the tree. Using the following method with an angular service sounds like it might be what you need:

I found a solution on this guy Jason Watmore's blog that describes using rxjs Observables and Subjects. Using this method allows data changes to easily propagate up and down the angular inheritance tree to any component you want

Briefly:

  1. You declare a service as a provider at the module.ts level with 3 methods:

    • sendMessage
    • clearMessage
    • getMessage
    \n\n\nimport { Injectable } from '@angular/core'; \n import { Observable } from 'rxjs'; \n import { Subject } from 'rxjs/Subject'; \n\n @Injectable() \n export class MessageService { \n    private subject = new Subject(); \n\n
     sendMessage(message: string) { this.subject.next({ text: message }); } clearMessage() { this.subject.next(); } getMessage(): Observable<any> { return this.subject.asObservable(); } 
    \n\n } \n
  2. This service needs imports of Observable and Subject from rxjs

  3. In each component you want to share data with:

    • create a subscription object in the constructor which calls the service.getMessage() function
    • call rxjs subscription.unsubscribe() in ngOnDestroy for each component so you aren't leaking memory
    • you can hook in a function to handle the incoming subscription updates
  4. When you have data you want to share with your other components:

    • Create a public method which calls the service.sendMessage() method
    • This will send your updated data to each component and fire those functions you've hooked in to handle the changed data

I believe the blog post I linked to and the plunkr from the post say it best and have really helped me move data around efficiently in my own app but if you have any questions I'll do my best to answer them

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM