Search code examples
angularrxjsangular5rxjs5angular-http

Angular 5 http.get into a BehaviorSubject to multicast data changes on the client


I have an angular 5 website which consumes a restful wcf web service. The web service, in turn, interacts with business objects, that talk to a database. I'm using the @angular/common/http module to consume the web service into an observable object which then renders on the web page. So far so good.

Now, am also updating the database via the web service, which also works fine.

But, it's a tad slow, and I would like to be able to update the Observable directly and simulaneously with the update web service call, so that the web site does not have to wait for the data to go through the web service, through the incredibly slow enterprise resource planning business objects, to the database, and then back down into the Observable objects, updating the screen via the async pipe.

So, I thought to myself, why not just replace the Observables with BehaviorSubjects? Then, I could just use the "next" method on the BehaviorSubject to quickly update the page.

But, when I try that...

public cartons$: BehaviorSubject<ICartonTrackDetail[]>;
this.cartons$ = this.cartonService.getCartonsObservable();

I get this error...

Type 'Observable<ICartonTrackDetail[]>' is not assignable to type 'BehaviorSubject<ICartonTrackDetail[]>'.
  Property '_value' is missing in type 'Observable<ICartonTrackDetail[]>'.```

Now, the error makes sense, but it makes me step back and wonder: What is the best way to accomplish my goal?


Solution

  • you want a subject that will let you inject client-side updates into the stream and you want to merge this subject with the observable that is streaming data from the server.

    Something like this:

    private clientStream$ : Subject<ICartonTrackDetail[]>;
    
    public cartons$ : Observable<ICartonTrackDetail[]>;
    
    // setup
    const serverStream = this.cartonService.getCartonsObservable();
    this.clientStream$ = new Subject<ICartonTrackDetail[]>();
    this.cartons$ = serverStream.merge(this.clientStream$);
    
    // when you get new data to send to server:
    this.clientStream$.next(newData);
    .. add code to send newData to server like normal ..
    

    Now any code subscribing to cartons$ will receive updates as you call clientStream$.next(newData)