1

I have some question about rxjs function. Actually, I make a request to http server. The way I receive data from http server is two steps because each request returns only 10 items, not entire items. Each request has page number so, if I have a total number of 100 items, I have to make quest 10 times. So, before making request one by one, I extract the total number of pages first, then I loop through request as many as the number of pages. In order to do it, I use switchMap function like below.

getItems(id: string) {
    return this.dataService.getPageNum(id).switchMap (
    (page_num: number) => { 

                for(let i=1; i<=page_num; i++) {
                    this.dataService.getItems(id, i).subscribe(
                        (data: Object) => {
                            this.items.push(data); 
                        }
                    )
                }
            }
        );
    }

It returns error error TS2345: Argument of type '(page_num: number) => void' is not assignable to parameter of type '(value: number, index: number) => ObservableInput<{}>'. Type 'void' is not assignable to type 'ObservableInput<{}>'.

So, I searched some information regarding this issue, I found something,

Angular 2 - RxJS Switch Map Issue

but I do not understand what question and answer says well. That means I should put Observable.empty() to make it work? Also, I even tried to return Observable.of(null) and Observable.empty(), it says that Property 'empty' does not exist on type 'typeof Observable' even I imported that function.

Anna Lee
  • 909
  • 1
  • 17
  • 37

1 Answers1

2

I glad you are getting familiar with rxjs. You have a couple of mistakes.

live example

  1. You are returning nothing inside of switchMap function. It expects from you do to so (return an observable), that is the purpose of mergeMap, switchMap and concatMap, to flat a map. Check this site, I hope it can help you to get started.

  2. You have to manage the subscription from the flated map not inside of the switchMap function. So this line is not correct:

this.dataService.getItems(id, i).subscribe(

your.component.ts

 getItems(id: string) {
           return this.dataService.getPageNum(id)
                     .switchMap((page_num: number) => {
                         for(let i=1; i<=page_num; i++) {
                             return this.dataService.getItems(id, i);
                         }
                     }).subscribe((data: Object) => {
                         this.items.push(data); 
                     });
         }
  1. And finally since the recommendation from rxjs core team is to use pipe operators, this is right solution, I mean the rxjs way:

import { switchMap } from 'rxjs/operators';

...

getItems(id: string) {
      return this.dataService.getPageNum(id)
                .pipe(switchMap((page_num: number) => {
                    for(let i=1; i<=page_num; i++) {
                        return this.dataService.getItems(id, i);
                    }
                })).subscribe((data: Object) => {
                    this.items.push(data); 
                });
    }
Luillyfe
  • 6,183
  • 8
  • 36
  • 46
  • Thank you, now I understand more clearly about switchMap. Here, getPageNum() is outer Observable while getItems() is inner Observable. While going through for loop, new Observable is returned and the returned observable is observed with Observer's subscription.. Is it right? – Anna Lee Mar 08 '18 at 13:05
  • Even though it gets late, it does not work as I expected.. I was kind of doubtful because it does not go through loop properly. – Anna Lee Mar 11 '18 at 16:08
  • This loop, this.dataService.getItems(id, i); goes through different page one by one. it returns Observable so I have to subscribe to each getItems loop. – Anna Lee Mar 11 '18 at 16:11
  • The solution is right as you can check in the live example. It solves the error you posted here, if you are not getting the results you are expecting, then post a new question/error message. – Luillyfe Mar 11 '18 at 21:11