Search code examples
angularrxjsangular-routingangular-httpangular-httpclient

angular - why observable chain doesn't terminate when piping a route.parame with a http.get using switchMap


Why doesn't the first chain complete?

switchMap is supposed to unsubscribe the previous observable and since http.get is one-time observable, I thought it would log complete.

Instead I'm keep getting the http.get results. This is what I'd expected of flatMap.

    this.route.params
        .pipe(
            switchMap(params => {
                return this.http.get('assets/data/module.json');
            })
        )

        .subscribe(
            res => {
                console.log(res);
            },
            e => e,
            () => console.log('complete')
        );

The default http.get results in a complete.

    this.http.get('assets/data/module.json').subscribe(
        res => {
            console.log(res);
        },
        e => e,
        () => console.log('complete')
    );

Solution

  • I think you got it wrong on what switchMap is supposed to do. switchMap will unsubscribe from the inner observable (your http.get call) if a new parameter is emitted. It will not unsubscribe from the parameters, once your http.get call is finished.

    What you want is to add the first() operator in your pipe before your switchMap operator. Also you might want to use mergeMap isntead of switchMap, though it should not matter in your case.

    this.route.params
        .pipe(
            first(),
            switchMap(params => {
                return this.http.get('assets/data/module.json');
            })
        )
    
        .subscribe(
            res => {
                console.log(res);
            },
            e => e,
            () => console.log('complete')
        );
    

    This will take the first parameter emitted by route.params, issue your http request and then complete the observable.

    An example for what switchmap can be used: Let's say we have a search field, where I can enter anything. When I enter something in the search field, angular will call the backend to retrieve the search result. Now it can happen that I change my search term, while the last search request is still pending. In that case, switchMap will cancel the old get request and issue the new one.