Search code examples
rxjssubject-observer

Angular 2 Subject.next not working once the Observable its listens throws an error


I'm struck at a scenario, where I have Angular service class (WeatherService) which performs a REST call to an external api and fetches data in searchWeather() function.

I have a component WeatherSearchComponent, which has input field search in its template which has keyup event bound to a function onSearch() in the component. Its basically a TypeAhead input field. I have a Subject defined in the class and in onSearch() function I'm initializing the next() function of the subject as below.

WeatherSearchComponent:

private searchStream = new Subject<string>();
onSearch(cityName:string) {
        this.searchStream
            .next(cityName);
    }

constructor(private _weatherService:WeatherService) {
    }

ngOnInit() {
        this.searchStream
            .debounceTime(300)
            .distinctUntilChanged()
            .switchMap((input:string) => this._weatherService.searchWeatherData(input))
            .subscribe(
              data => this.data = data
            );
    }

WeatherService:

searchWeatherData(cityName: string): Observable<any> {
        return this._http.get('URL')
            .map(response => response.json())
            .catch(error => {
                console.error(error);
                return Observable.throw(error.json())
            });
    }

The issue I'm facing is, if the REST call fails or returns an error, Im logging it, but the Subject searchStream life cycle is ending once it gets an error and its not accepting inputs after that. I tried handling the error in the ngOnInit() method but its not working.

I would like to know how to handle this scenario?


Solution

  • It's not an issue with the Subject. This is general Rx behavior. When you send an error notification the chain is disposed.

    You're already using .catch() so you can just modify its callback not to rethrow the error but suppress it or whatever you want:

    .catch(error => {
        console.error(error);
        return Observable.empty()
    });
    

    By the way, Subjects do have an internal state you should be aware of, but in your use-case the error doesn't reach the Subject.