Search code examples
angularrxjsangular8rxjs-observablesswitchmap

How to finilize rxjs switchmap observable?


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?


Solution

  • 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))
        )
      )
    )