Observable returns undefined

Viewed 157

I've got a problem with a service in my application. I have a service where I have an observable. That observable also contains another observable and two other functions as well which are processing the data from the inner observable. The problem is that when I load the app the very first time I get undefined because the service returns the outer observable before the inner observable and the data modifying functions are done. I was told I can use switchMap for this, but I got really confused with that. Can anybody help out how to use the switchMap so the outer observable waits for the inner observable and the functions before returning any value?

This is how the service looks like:

  fetchFilteredReservations(filterBy: any, search: any): Observable<any> {
    this.reservation.fetchReservations().subscribe((data: any) => {
      const data1 = this.loopData(data)
      const data2 = this.switchData(data1, filterBy, search)
      this.filteredReservations = data2
    });
      return of(this.filteredReservations);
  }

  loopData(data: any) {
    let loopData = data
    loopData.forEach((element: any) => {
      let year: any = 0;
      let month: any = 0;
      let day: any = 0;
      day = element.createdDate.slice(0, 1);
      if (day < 10) {
        day = '0' + day;
      }
      month = element.createdDate.slice(2, 4);
      if (month < 10) {
        month = '0' + month;
      }
      year = element.createdDate.slice(5, 9);
      let date = `${year}-${day}-${month}`;
      element.createdDate = date;
      if (this.user === element.user) {
        element.canDelete = true;
      } else {
        element.canDelete = false;
      }
    });
    return loopData
  }

  switchData(data: any, filterBy: any, search: any){
    let filterData = []
    switch (filterBy) {
      case 'createdBy':
        return filterData = data.filter(
          (element: any) => element.user.includes(search)
        );
      case 'createdFor':
        return filterData = data.filter(
          (element: any) => element.reservedFor.includes(search)
        );
      case 'createdOn':
        return filterData = data.filter(
          (element: any) => element.createdDate.includes(search)
        );
      case 'reservedDate':
        return filterData = data.filter(
          (element: any) => element.reservedDateData.includes(search)
        );
      case 'desk':
        return filterData = data.filter(
          (element: any) => element.name.includes(search)
        );
    }
  }

Thanks for any help.

2 Answers

I think you want something like this:

fetchFilteredReservations(filterBy: any, search: any): Observable<any> {

    this.reservation.fetchReservations().pipe(
      switchMap((data: any) => {
          const data1 = this.loopData(data);
          const data2 = this.switchData(data1, filterBy, search);
          this.filteredReservations = data2;
          return data2; // or this.filteredReservations
      })
    );
}

I think you should use the pipe operator. I just did this on the fly but it would look like :

fetchFilteredReservations(filterBy: any, search: any): Observable<any> {
    return this.reservation.fetchReservations().pipe(
        map((data: any): any => 
            const data1 = this.loopData(data)
            const data2 = this.switchData(data1, filterBy, search)
            this.filteredReservations = data2
            return this.filteredReservations
        ),
    )
  }

doc

Related