component which is calling submitUser
this.someservice.submitUser(postData).subscribe((data) => {
this.viewUsers();
}, (err) => {
console.log('error in the component', err);
});
Here is the service file with submitUser function
public submitUser(reqBody ) {
return this.httpService.post('roles', reqBody, '/business/create')
.pipe(
catchError(
this.httpService.handleError())
);
}
and here is the httpService Post and handleError methods
public post<JSON>(url: string, body: any, param?: string, options?: IRequestOptions): Observable<JSON> {
return this.intercept(this.http.post<JSON>(this.getURLFromMethodName(url, param), body, this.requestOptions(options)));
}
handleError<T> (operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
// TODO: send the error to remote logging infrastructure
console.error('error from httpclient', error); // log to console instead
throw throwError(new Error(error));
};
}
handleError adisplays the console error, I am trying to return/capture this error in my submitUser function in service.ts
How do i do that ? Any Inputs appreciated, Thanks
Your handleError() method returns an error observable along with logging the error to the console.
When some error occurs, the catchError operator takes that error and gives it to handleError() which in turn returns an error observable.
CASE 1: Returning the error
If you need to pass this error on to the subscriber, you don't have to do anything. The catchError operator is already taking care of it for you.
With the same code, let's say some component is consuming your service, then you can just write
someService.submitUser().subscribe((res) => {
\\ handle success
}, (err) => {
console.error(err); // Will print the error
});
Whenever the error occurs, the catchError is going to return the error observable back to its subscriber and it will go in the error function of the observer as shown in the code snippet above.
CASE 2: Handling the error
The catchError operator accepts a function that takes error as an argument. If you return another observable inside this instead of throwing an error, the subscriber won't get to know that the error had occurred, the success function of the observer will execute.
// Inside the service
public submitUser(reqBody ) {
return this.httpService.post('roles', reqBody, '/business/create')
.pipe(
catchError((err) => of([1,2,3]));
}
// Inside the component consuming the service
someService.submitUser().subscribe((res) => {
console.log(res) // Will print [1,2,3]
}, (err) => {
\\ handle error
});
Related
I'm trying to use the AngularFire library in an Angular application. Some of the AngularFire calls return promises, and I'd like to handle them as observables instead for consistency throughout the app. I'm using rxjs v6
Using from() works well and gives the expected behaviour except when errors occur.
If the promise throws an exception, the observable doesn't seem to see it and a stack trace gets dumped in the console saying Error: Uncaught (in promise).
My first attempt
The AngularFire call that returns the promise:
deleteCampaign(id: string) {
return from(this.campaignCollection.doc(id).delete());
}
The calling code:
deleteCampaign(id: string) {
return this.dataStorageService.deleteCampaign(id)
.pipe(
catchError(
err => {
console.log('error when deleting campaign');
console.log(err);
return throwError(err);
}
)
);
}
In this instance, I get the stack trace in the console and the catchError never fires.
My second attempt
I added a catch to the promise inside the from, and then tried rethrowing the error as an observable so it looked like this:
deleteCampaign(id: string) {
return from(this.campaignCollection.doc(id).delete().catch(
err => {
throwError(err);
}
));
}
My third attempt
Much like the second attempt, but I tried throwing a plain javascript error. This resulted in the same stack trace however, and it wasn't picked up by the observable either.
deleteCampaign(id: string) {
return from(this.campaignCollection.doc(id).delete().catch(
err => {
throw(err);
}
));
}
This stopped the stack trace happening, as now the promise was catching it, but the calling code still never sees the error.
Am I going about this the wrong way? I assumed that by using from() all of the error handling could occur in the observable, and I could leave the promise alone.
I need to be able to either:
1. Have no error handling code where the promise is returned and let the observable take care of it.
1. Have the promise catch block able to rethrow an error thats caught by the observable.
Here's the solution arrived at:
From the front end component, handle the passed error using the error callback in subscribe
onDelete(id: string) {
this.loadingCampaigns = true;
this.campaignService.deleteCampaign(id).subscribe(
_ => {},
err => {
console.log('error detection from the component');
}
);
}
From the campaign service, tap() the error so it can be logged or otherwise:
deleteCampaign(id: string) {
return this.dataStorageService.deleteCampaign(id)
.pipe(
tap(null, () => {console.log('tapped the error');} ),
);
}
Finally, from the data storage component do nothing at all:
deleteCampaign(id: string) {
return from(this.campaignCollection.doc(id).delete());
}
You can attach an error callback to Observable.subscribe().
Rx.Observable.from(Promise.reject('Boo!'))
.subscribe(val => {
console.log('success');
},
err => {
console.log(err);
});
// Boo!
deleteCampaign(id: string) {
return from(this.campaignCollection.doc(id).delete()).pipe(catchError(err=>{
return throwError(err);
}))
}
deleteCampaign(myid).susbcribe(res=>{
console.log(res);
},error=>{
console.log(error)
})
I put an example using ng-bootstrap modal -that return a promise when open the modal- to convert to a Observable in this stackblitz
I am using the below methods to send data. I want to display an error response on my component. How can I console log error message in my component?
component.ts
signup(){
return this.loginservice.signupUser(this.model).subscribe(data => {
console.log(data.error);
});
}
service ts
signupUser(signupuserModel: any = {}):Observable<any>{
return this.http.post(`${this.signuouserurl}`,signupuserModel)
}
error message
In RxJS, subscribe() method can have 3 functions
next() if observable emits value.
error() if there's an error thrown from the Observable
complete() if the observable is completed.
What you need to do is to add an extra arrow function in your server call inside subscribe() method
public error: any;
signup() {
return this.loginservice.signupUser(this.model).subscribe(success => {
console.log(success);
}, error => { // second parameter is to listen for error
console.log(error);
this.error = error;
});
}
If you want to show the error in your component.html, you can use the interpolation {{ }}
component.html
<div class="error">{{ error }}</div>
try
signup() {
return this.loginservice.signupUser(this.model).subscribe(data => {
console.log(data);
}, err => {
console.log(err);
});
}
You can also use try-catch approach in following way
async signup() {
try {
let data = await this.loginservice.signupUser(this.model).toPromise();
console.log(data)
} catch (e) {
console.log(e);
}
}
However not all http codes raise exception
you can choose any method to display an error.. on of the best way is seprate the success and error response with following code (for this your http call must thrown an exception if not then you have to chose the second option )
signup() {
return this.loginservice.signupUser(this.model).subscribe(success => {
console.log(success);
}, error => {
console.log(error);
});
}
or you can write conditional code like
signup() {
return this.loginservice.signupUser(this.model).subscribe(success => {
console.log(data);
if(success.status == 406){ console.log("success")}
else { console.log("Error ") }
}
}
while learning how to handle errors in Angular Typescript threw an error
Property 'subscribe' does not exist on type 'OperatorFunction<{}, {}>'
in this code block in my component
createPost(post: HTMLInputElement) {
this.service.newPost(post).subscribe(
response => {
this.posts.splice(0, 0, post);
},
(error: AppError) => {
if (error instanceof BadInput) {
// Set form errors and display them next to input fields
this.form.setErrors(error.originalError);
} else {
alert("An unexpected error occurred.");
console.log(error);
}
}
);
}
The service code returning the observable used by the component code is
newPost(post) {
return (
this.http.post(this.url, post),
catchError((error: Response) =>
error.status === 400
? Observable.throw(new BadInput(error))
: Observable.throw(new AppError(error))
)
);
}
I need help resolving the error and an explanation on why the error is thrown or how best to achieve handling errors.
You should use pipe operator followed by a map operator followed by catchError operator. You will have to import the map operator and the catchError operator from rxjs/operators. Please see below:
.pipe(
mergeMap(resp => {
// add logic
}),
catchError(err => {
// add handling
})
);
So something strange is going on, I am making an HTTP get in my service but I am getting an error, the strange thing is it sometimes works and sometimes doesn't, but for the past 24 hours it's not been working anymore. Code for a service call and subscription are below. and then also the error.
category.service.ts
getcategory(id) {
const url = `${this.localUrl}category/${id}`;
return this.http.get<CategoryResponse>(url)
.pipe( catchError(this.errorHandler) );
}
Error Handler
errorHandler(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError('Something bad happened; please try again later.');
}
add-edit-category.component.ts
if (this.router.url.indexOf('edit') >= 0) {
this.route.paramMap.pipe(switchMap((params: ParamMap) =>
this.categoryService.getcategory(params.get('id'))))
.subscribe(results => {
this.category = results.category;
this.categoryNameControl.setValue(this.category.categoryName);
this.categoryDescriptionControl.setValue(this.category.categoryDescription);
console.log("I am edit", Object.keys(config))
console.log("TEst again", this.category)
}, error => {
console.log("Error", error)
});
}
Error
Error TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at Object.push../node_modules/rxjs/internal/util/subscribeTo.js.exports.subscribeTo (subscribeTo.js:42)
at Object.subscribeToResult (subscribeToResult.js:7)
at SwitchMapSubscriber.push../node_modules/rxjs/internal/operators/switchMap.js.SwitchMapSubscriber._innerSub (switchMap.js:103)
at SwitchMapSubscriber.push../node_modules/rxjs/internal/operators/switchMap.js.SwitchMapSubscriber._next (switchMap.js:96)
at SwitchMapSubscriber.push../node_modules/rxjs/internal/Subscriber.js.Subscriber.next (Subscriber.js:103)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/map.js.MapSubscriber._next (map.js:81)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:93)
at BehaviorSubject.push../node_modules/rxjs/_esm5/internal/BehaviorSubject.js.BehaviorSubject._subscribe (BehaviorSubject.js:26)
at BehaviorSubject.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (Observable.js:176)
at BehaviorSubject.push../node_modules/rxjs/_esm5/internal/Subject.js.Subject._trySubscribe (Subject.js:96)
I'm facing problem when catching the error from the API. As you can see below, I'm calling deletedJob method when clicks on delete button and that function call 'deleteJob' function of jobService.
In Component
deleteJob(id) {
this.jobService.deleteJob(id, this.shopId)
.then(res => {
console.log('response');
// Displaying the success message
})
.catch(this.handleError)
}
});
}
deletedJob function in jobService component
deleteJob(id: number, shopId: number) {
let url = this.jobsUrl() + `/${id}.json`;
return this.http
.delete(url)
.toPromise()
.then(res => res.json().response)
.catch(this.handleError);
}
handleError function for above function
handleError(error: any) {
return Promise.reject(error.message || error);
}
So when rejecting that error through handleError function, I'm getting an error in console 'TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.'