Search code examples
rxjsrxjs-observablesrxjs-pipeable-operatorsswitchmapcombinelatest

undefined when combine combineLatest and switchMap


I'm trying to combine two Observables to have few values for the call to service method that accepts two values. But here I have few errors

  • Argument of type '([filter, sort]: [string, string]) => void' is not assignable to parameter of type '(value: [string, string], index: number) => ObservableInput'. Type 'void' is not assignable to type 'ObservableInput'.

  • in console -

    You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. at subscribeTo (subscribeTo.js:27) at innerSubscribe (innerSubscribe.js:71) at SwitchMapSubscriber._innerSub (switchMap.js:44) at SwitchMapSubscriber._next (switchMap.js:34) at SwitchMapSubscriber.next (Subscriber.js:49) at CombineLatestSubscriber.notifyNext (combineLatest.js:73) at InnerSubscriber._next (InnerSubscriber.js:11) at InnerSubscriber.next (Subscriber.js:49) at BehaviorSubject._subscribe (BehaviorSubject.js:14) at BehaviorSubject._trySubscribe (Observable.js:42)

  1. Defining Observables and Subjects.

     private openSortQuerySubject: BehaviorSubject<string> = new BehaviorSubject<string>(this.formatSortQuery(this.multiSortMeta));
     public openSortQuery: Observable<string> = this.openSortQuerySubject.asObservable();
    
     private closedSortQuerySubject: BehaviorSubject<string> = new BehaviorSubject<string>(this.formatSortQuery(this.multiSortMeta));
     public closedSortQuery = this.closedSortQuerySubject.asObservable();
    
  2. Combine observables.

       const openQueries$ = combineLatest([this.openFilterQuery, this.openSortQuery]);
       const closedQueries$ = combineLatest([this.closedFilterQuery, this.closedSortQuery]);
    
  3. Use merged values in service method.

openQueries$
      .pipe(
        switchMap(([filter, sort]) => {
          this.alertService
            .listAlerts(filter, sort);
        }),
        tap(v => console.log(v))
      )
      .subscribe((openAlerts) => {
        this.openAlertsCount = openAlerts.length;
        this.openAlerts = this.parseAlerts(openAlerts);
      });

    closedQueries$
      .pipe(
        switchMap(([filter, sort]) => {
          this.alertService
            .listAlerts(filter, sort);
        })
      )
      .subscribe((closedAlerts) => {
        this.closedAlertsCount = closedAlerts.length;
        this.closedAlerts = this.parseAlerts(closedAlerts);
      });

Solution

  • You have to return an observable (or something RxJS knows how to turn into an observable) within a switchMap callback.

    Not this:

    switchMap(([filter, sort]) => {
      this.alertService.listAlerts(filter, sort);
    })
    

    But this (assuming listAlerts returns an observable, a promise or similar):

    switchMap(([filter, sort]) => {
      return this.alertService.listAlerts(filter, sort);
    })