2

I have an observable in my angular 8 project, and subscribing in ngOnInit().

     export class ChartComponent implements OnInit {
       urlSubject: Subject<string> = new Subject();
       isLoading: BehaviorSubject<boolean> = new BehaviorSubject(false);
       chartData: BehaviorSubject<any[]> = new BehaviorSubject<any[]>([]);
       dataSubscription: Subscription;

       dataObservable: Observable<any> = this.urlSubject.pipe(
         switchMap((url: any) => this.httpClient.get<any[]>(url))
       )

       ngOnInit() {
         this.dataSubscription = this.dataObservable
          .pipe(tap(() => this.isLoading.next(true)))          
          .pipe(map((response: any) => response.result))      
          .subscribe((response: any) => this.chartData.next(response),
            () => this.isLoading.next(false),
            () => this.isLoading.next(false));

         this.urlSubject.next(this.data.settings.dataEndpoint)
      }
}

But complate method does not fire of subscribe.

I am subscribing to chartData that type is BehaviourSubject. So I do not subscribe to urlSubject. Because the url may change any time for searh or filter parameters.

I am using finilize but it does not work. I think this problem is about switchmap inner porecess. How can I finilize and set loading to false?

Marek Szkudelski
  • 1,102
  • 4
  • 11
barteloma
  • 6,403
  • 14
  • 79
  • 173
  • 1
    if `urlSubject` is a Subject then it never completes until you call `urlSubject.complete()`. So it's not the inner observable returned to `switchMap` that needs to be completed. – martin Apr 14 '20 at 07:31
  • `urlSubject` is a Subject, I updated the post. So what can I do? – barteloma Apr 14 '20 at 07:45
  • It really depends on what you want to do. Maybe in your situation you could just move `finalize()` into the inner observable. Like this `this.httpClient.get(url)).pipe(finalize(() => ...))` – martin Apr 14 '20 at 10:27

2 Answers2

6

You need to use finalize on the httpClient.get. Subject and BehaviorSubject doesn't complete until you do it manually by calling subject.complete(). However Observable created by the httpClient completes after emitting api response and you need to use that.

For your example:

dataObservable: Observable<any> = this.urlSubject.pipe(
  tap(() => this.isLoading.next(true)),
  switchMap((url: any) =>
    this.httpClient.get<any[]>(url).pipe(
      finalize(() => this.isLoading.next(false))
    )
  )
)
TmTron
  • 17,012
  • 10
  • 94
  • 142
Goga Koreli
  • 2,807
  • 1
  • 12
  • 31
1

As mentioned above subjects never complete, unless you call subject.complete();

With that said, subjects are observables, you can always unsubscribe from them using take(COUNT) or takeUntil operators etc....

Eliran Eliassy
  • 1,590
  • 12
  • 25