Actually I want to catch errors on all http requests using custom decorators.
My actual code looks like this:
createRecord(data: data) {
return this.httpClient.post(`${this.apiURL}/record/`, data);
}
I want to convert these kind of functions to something like this:
createRecord(data: data) {
return this.httpClient.post(`${this.apiURL}/record/`, data)
.pipe(tap((data)=>console.log(data)),catchError(handleError)));
}
I know this is possible using http interceptors but I tried it using custom method decorators. My decorator looks like this:
export function CatchHttpError() : MethodDecorator {
return function ( target : any, propertyKey : string, descriptor : PropertyDescriptor ) {
const original = descriptor.value;
descriptor.value = original()
.pipe(
tap((data)=>console.log('tap entered: data = ',data)),
catchError(handleError)
);
return descriptor;
};
}
And then I decorate the function like this:
@CatchHttpError()
createRecord(data: data) {
return this.httpClient.post(`${this.apiURL}/record/`, data);
}
But the problem here is that it tries to execute the function then only when I initialize this particular service, not when I actually call createRecord method. How do I modify the method decorator to achieve this result?
If you want the decorator to alter the behavior of the method it's applied on, you need to override the original method from within the decorator :
export function CatchHttpError() : MethodDecorator {
return function (target : any, propertyKey : string, descriptor : PropertyDescriptor ) {
const original = descriptor.value;
// override the method
descriptor.value = function(...args: any[]) {
// Calling the original method
const originalResults = original.apply(this, args);
return originalReults.pipe(
tap((data) => console.log('tap entered: data = ',data)),
catchError(handleError)
);
}
}
Note that it's important to define the override with the function
keyword and not an arrow function to be able to use the this
of the class context.