Angular promise handling decorator on an async method

226 Views Asked by At

I have a lot of places in my app where failed async method calls need to be treated in the same way: showing a toaster and logging the error in the console. For this purpose I'm writing a decorator for an Angular controller method. Suppose the method is an async function such as:

@ToastOnFail
async makeCall() {
  const result = await this.httpService.makeSomeRequest();
  // do stuff with the result
}

and my decorator looks like this

export default async function ToastOnFail(
  target: any,
  propertyKey: string,
  descriptor: PropertyDescriptor
) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args) {
    const toasterService = AppModule.injector.get<ToasterService>(
      ToasterService as Type<ToasterService>
    );
    return originalMethod.apply(this, args)
      .catch((err) => {
        toasterService.addGenericActionIncompleteError();
        console.error(err);
      });
  };
}

I get a compilation error

error TS1241: Unable to resolve signature of method decorator when called as an expression. Type 'Promise' has no properties in common with type 'TypedPropertyDescriptor<() => Promise>'.

I'm not sure whether is a TS confusion and I have to do some manual casting or if I'm not returning what I should be returning from the decorator. What am I missing?

1

There are 1 best solutions below

1
On

disclamer it's not an answer to your problem

Why not use a "custom operator"? here there're a great link about custom operator. In this way you "act" about observables

Some like

function debug<T>(toasterService:ToasterService) {
  return function<T>(source: Observable<T>): Observable<T> {
    return source.pipe(catchError((err:any)=>{
      toasterService.addGenericActionIncompleteError()
      return throwError(err) //or return of(null)
    }));
  };
}

Allow you write

const result = this.httpService.makeSomeRequest().pipe(debug(this.myToaster));