I see a lot of tutorials doing something like this:
http.get("...").subscribe(
success => console.log('hello success'),
error => console.log('bye error')
);
I don't know how this works, since there aren't any types or anything, however I tried to do that myself and I end up that the request always goes into success, even if I have an error. What is the problem?
Troublemaker:
this.memberService.create(this.currentMember)
.subscribe(
success => {
let mem: Member = success.json() as Member;
if (this.selectedOrganization) {
this.addMemberToOrganization(mem);
} else if (this.selectedServiceProvider) {
this.addMemberToServiceProvider(mem);
} else {
this.toastsService.error("lbl_users_service_provider_and_organization_undefined");
}
},
error => console.log(error)
);
Create-Method in the memberService:
create(member: Member): Observable<any> {
return this.http
.post(this.RESOURCE_BASE_URL, member)
.map(response => {
if (response.status === 200) this.toastsSerivce.success(this.translateService.instant('lbl_users_member_created'));
return response;
})
.catch(error => this.toastsSerivce.error(this.translateService.instant('lbl_users_member_create_failed')));
}
I even catch the error, but the subscribe
part doesn't seem to care.
It fails at success.json()
, because if there is an error, there is no json
. But if there is an error, I want it to call the error =>...
instead of the success
. Any advice is highly appreciated.
Catch errors in the observable stream Another option to catch errors is to use the CatchError Operator. The CatchError Operators catches the error in the observable stream as and when the error happens. This allows us to retry the failed observable or use a replacement observable.
When the error occurs in the HTTP Request it is intercepted and invokes the catchError . Inside the catchError you can handle the error and then use throwError to throw it to the service. We then register the Interceptor in the Providers array of the root module using the injection token HTTP_INTERCEPTORS .
The Observable Contract and Error Handling Network requests can fail, for example. A stream can also complete, which means that: the stream has ended its lifecycle without any error. after completion, the stream will not emit any further values.
The basic way to handle errors in Angular is to use Angular's HttpClient service along with RxJS operators throwError and catchError. The HTTP request is made, and it returns the data with a response if anything wrong happens then it returns an error object with an error status code.
I think the issue is that you are not throwing
the error with an Observable.throw(errMsg)
.
So, you may just use it like this:
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
In your example:
create(member: Member): Observable<any> { return this.http .post(this.RESOURCE_BASE_URL, member) .map(response => { if (response.status === 200) this.toastsSerivce.success(this.translateService.instant('lbl_users_member_created')); return response; }) .catch((error:any) => Observable.throw(this.toastsSerivce.error(this.translateService.instant('lbl_users_member_create_failed')))); }
But, you could use an error handler, like the one Angular proposes here:
private handleError (error: Response | any) { // In a real world app, you might use a remote logging infrastructure let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = body.error || JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''} ${err}`; } else { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); return Observable.throw(errMsg); }
And so, your method would look more like this:
create(member: Member): Observable<any> { return this.http .post(this.RESOURCE_BASE_URL, member) .map(response => { if (response.status === 200) this.toastsSerivce.success(this.translateService.instant('lbl_users_member_created')); return response; }) .catch(this.handleError); }
It's actually cleaner and more reusable for other methods that you may create within your service.
I would suggest to use also a response handler, like the one used by Angular's devs: this.extractData
.
Obviusly, inside the error handle method you can put your own custom logic, depends on how you want to show or handle the error.
NOTE: I did not test your code nor the code I posted here. But I wanted to show/express the concept. You should throw the error in order to not going into success
everytime. How you handle it depends on you and your App.
It works for me:
this.http.post('http://example.com/path/', {sampleData: 'd'}).subscribe(
res => {alert('ok!');},
err => {alert(err.error)}
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With