After an error-response from the server my app does not send any further requests.
I'm sending a request with:
getMachineRules(rules: Array<string>): Observable<RulesResults> {
return this.http.post<RulesResults>('/rules', { nodes: rules })
.pipe(
catchError(this.handleError)
);
}
My errorHandler:
handleError(error) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${JSON.stringify(error.error)}`);
}
return throwError('Something bad happened; please try again later.');
}
And my pipeline looks like this:
ngAfterViewInit() {
this.rulesChanged
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.settings.getMachineRules(this.currentRules);
}),
map(data => {
this.isLoadingResults = false;
this.resultsLength = data.inputs?.length || 0;
return data;
}),
catchError(e => {
console.log("Error caught");
this.isLoadingResults = false;
this.resultsLength = 0;
return observableOf({ inputs: [] } as RulesResults);
})
).subscribe(
data => { return this.updateRules(data); },
);
}
I can see the "Error caught" message in the console and the method updateRules()
seems to work properly even in the error case.
However after a 404-Error-Response the ngAfterViewInit()
method is
not called anymore. The UI steel reacts on interactions.
Once an Obsevable is failed there is nothing you could do to make it active again, catchError
is used to handle errors by returning a new observable or throwing an error. observableOf({ inputs: [] } as RulesResults)
is served as substitute in case the main stream fails, meaning your main Observable will never emit again.
Consider using retry
at the end of your pipeline, or optionally have your
catchError
return the source Observable itself, as demonstrated below:
catchError((error, source) => {
....
return source;
})
Alternately put the catchError
operator inside a switchMap
so that only the inner stream will fail while the the outer (main) stream will remain active, as below:
ngAfterViewInit() {
this.rulesChanged
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.settings.getMachineRules(this.currentRules).pipe(
map(data => {
this.isLoadingResults = false;
this.resultsLength = data.inputs?.length || 0;
return data;
}),
catchError(e => {
console.log("Error caught");
this.isLoadingResults = false;
this.resultsLength = 0;
return observableOf({ inputs: [] } as RulesResults);
})
)
})
).subscribe(
data => { return this.updateRules(data); },
);