Home > Software design >  How to combine the similar rxjs streams?
How to combine the similar rxjs streams?

Time:09-21

I have the following RXJS streams:

    this.widthBorder$.pipe(skip(1)).subscribe((value) => {
        this.registryBoundaries.setAttribute('stroke-width', `${value || 0}`);
    });

    this.widthBorderColor$.pipe(skip(1)).subscribe((value) => {
        this.registryBoundaries.setAttribute('stroke', `${value || 0}`);
    });

    this.drawContour$.pipe(skip(1)).subscribe((value) => {
        this.registryBoundaries.style.display = value ? 'block' : 'none';
    });

As you can see there are a duplicates of code like skip(1) also there methods are the similar?

I skip first value because all streams are BehaviorSubject.

How to optimize it?

CodePudding user response:

It seems that you should use Subject instead of BehaviorSubject for this case. Subject will emit no initial value upon subscription and this will save you the need to use the skip operator.

For reading from multiple observables, there is no magic solution. You may use a thing like zip so you have an array of emitted values of the observables (but you will have to pipe each observable with startWith(null) so they emit a value, since zip will only emit once all observables have emitted). You may also use merge to simply fuse all observables into a single observable, but you won't be able to tell which observable has emitted the received value unless you add some sort of tag.

I think your implementation is fine once you switch from BehaviorSubject to Subject and remove all the skip operators. If you had ten more subscriptions like this, I would suggest creating the observables programatically, but for three subscriptions nothing will save you much lines of code.

CodePudding user response:

just use Subject instead of BehaviorSubject

BehaviourSubject

BehaviourSubject will return the initial value or the current value on Subscription

Subject

Subject does not return the current value on Subscription. It triggers only on .next(value) call and return/output the value

public widthBorder$ = new Subject();
public widthBorderColor$ = new Subject();
public rawContour$ = new Subject();

this.widthBorder$.subscribe(v => this.setAttribute('stroke', `${v || 0}`));

this.widthBorderColor$.subscribe(v => this.setAttribute('stroke-width', `${v || 0}`));

this.drawContour$.subscribe((value) => {
    this.registryBoundaries.style.display = value ? 'block' : 'none';
});

public setAttribute(attr: string, value: string): void {
    this.registryBoundaries.setAttribute(attr, value);
}
  • Related