Home > OS >  Angular12 - injecting service into function
Angular12 - injecting service into function

Time:09-23

So, we've got Graphql response handler

export const handleResponse = (operation: DocumentNode): OperatorFunction<any, any> => {
  return pipe(
    map((response: any) => {
      const definition = operation.definitions[0] as OperationDefinitionNode;
      const selection = definition.selectionSet.selections[0] as FieldNode;
      const selectionName = selection.name.value ?? null;
      if (!selectionName) {
        throw new Error(`${selection.kind} name must be present.`);
      }
      if (response.data[selectionName]?.errors) {
        handleError(response.data[selectionName].errors);
      }
      return response.data[selectionName];
    }),
  );
};

const handleError = (errors: string[]) => {
  if (Array.isArray(errors) && errors.length) {
    const errorArrayToString = errors.map(error => JSON.stringify(error)).toString();
    throw new Error(errorArrayToString);
  }
};

It does works pretty well, but I also want to use notification service. I want to do something like that

const handleError = (errors: string[]) => {
  if (Array.isArray(errors) && errors.length) {

    notificationsService.show('Any error message')

    const errorArrayToString = errors.map(error => JSON.stringify(error)).toString();
    throw new Error(errorArrayToString);
  }
};

CodePudding user response:

You need to inject the service inside a variable

import { Component, Injector, OnInit } from '@angular/core';
import { NotificationsService } from './custom.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {

  // @Constructor services injectors

  notificationsService: NotificationsService;

  /**
   * Constructor
  */
  constructor(
    private _injector: Injector
  ) {
    this.notificationsService = this._injector.get<NotificationsService>(NotificationsService);
}

 ngOnInit(): void {
 }

 //custom error handler
 handleError (errors: string[]) => {
  if (Array.isArray(errors) && errors.length) {

    this.notificationsService.show('Any error message')

    const errorArrayToString = errors.map(error => JSON.stringify(error)).toString();
    throw new Error(errorArrayToString);
  }
};
}

CodePudding user response:

Thanks, but I decided to move this logic into HTTP interceptor. Here is the code

@Injectable()
export class ApolloErrorInterceptor implements HttpInterceptor {
  constructor(private _notificationsService: TuiNotificationsService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      tap((response: any) => {
        if (request.body?.operationName) {
          const operationName = request.body.operationName;

          if (response.body?.data[operationName]?.errors) {
            response.body.data[operationName].errors.forEach((error: any) => {
              this._notificationsService
                .show(error.message, { status: TuiNotification.Error, autoClose: 5000 })
                .subscribe();
            });
          }
        }
      }),
    );
  }
}

It will intercept only those responses that have an "operationName" in the body, which is Graphql responses

But now you need to explicitly make sure to specify the name of the request

query example and mutation example

  • Related