Перенаправление на компонент в Angular на основе кода ошибки - PullRequest
1 голос
/ 20 февраля 2020

Я обрабатываю ошибки четырьмя частями ... перехватчик http для ошибок, возвращаемых сервером, глобальный обработчик ошибок, основанный на встроенном обработчике ошибок Angular. служба ошибок, которая регистрирует ошибки в серверной службе для целей поддержки и компонент диалога материалов для отображения дружественного сообщения для конечного пользователя.

Есть некоторые ошибки, при которых мы sh фиксируем ошибку код состояния и перенаправление на компонент для более удобного взаимодействия с конечным пользователем.

Один из примеров - 404. У нас есть не найденный компонент. Если состояние ошибки сервера 404, я хочу перенаправить на не найденный компонент и не отображать диалоговое окно ошибки.

Вот мой перехватчик ...

import { Injectable } from '@angular/core';
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
import { MatDialog } from '@angular/material';
import * as StackTrace from 'stacktrace-js';
import { ErrorDialogComponent } from './error-dialog.component';
import { PathLocationStrategy } from '@angular/common';
import { ErrorService } from './error.service';
import { LoggerService } from './logger.service';
import { Router } from '@angular/router';

@Injectable()
/**
 * HttpErrorInterceptor to grab errors during http calls and log them
 *
 * @param (clientId) client id
 */
export class HttpErrorInterceptor implements HttpInterceptor {
  /**
   * constructor to grab errors during http calls and log them
   *
   * @param (dialog) MAT dialog to display to end user
   * @param (errorService) error service to grab error messages
   * @param (logger) logger service to post log errors to api and mantis
   */
  constructor(
    public dialog: MatDialog,
    private errorService: ErrorService,
    private logger: LoggerService,
    private router: Router
  ) {}
  /**
   * Interecept to grab request, deal with it and pass it along
   *
   * @param (request) http request
   * @param (next) send request to next http handler
   */
  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    // return the next statement
    return next.handle(request).pipe(
      // retry the call once
      retry(1),
      // catch the error
      catchError((error: HttpErrorResponse) => {
        if (error.status === 404) {
          console.log('error.status: ', error.status);
          // this.router.navigate(['']);
        } else {
          // Message variable to hold error message
          let errorMessage = '';
          // Variable to hold url location of error
          const url =
            location instanceof PathLocationStrategy ? location.path() : '';
          // server-side error
          errorMessage = this.errorService.getServerMessage(error);
          // get the stack trace, lets grab the last 10 stacks only
          StackTrace.fromError(error).then(stackframes => {
            const stackString = stackframes
              .splice(0, 20)
              .map(function(sf) {
                return sf.toString();
              })
              .join();
            /**
             * Function to log errors to api and mantis
             *
             * @param (errorMessage) error message passed to function
             * @param (url) url passed to function
             * @param (stackString) stackString passed to function
             */
            this.logger
              .createErrorLog(errorMessage, url, stackString)
              .subscribe(
                result => {
                  console.log('log filed: ', result);
                },
                (err: any) => console.log(err)
              );
          });
          // Check if error is undefined and open dialog with appropriate error info
          if (typeof errorMessage !== 'undefined') {
            this.openDialog(errorMessage);
          } else {
            this.openDialog('undefined');
          }
          // throw error
          return throwError(errorMessage);
        }
      })
    );
  }
  /**
   * Function to open dialog to display error
   *
   * @param (data) error data to display
   */
  openDialog(data): void {
    // Constant to hold and call dialog to display error
    const dialogRef = this.dialog.open(ErrorDialogComponent, {
      width: '60%',
      data: data
    });
    // Code to run after the dialog is closed
    dialogRef.afterClosed().subscribe(result => {
      // Redirect back to home (dashboard)?
    });
  }
}

Как вы можете видеть У меня есть простой, если я проверяю код состояния. Затем у меня есть вызов метода navigate, в котором я пытаюсь выполнить маршрутизацию к нулю, поскольку в модуле моего маршрутизатора не найден компонент, указанный в качестве маршрута «none».

Это перенаправление, но также отображается диалоговое сообщение об ошибке. Я не хочу, чтобы это отображалось. Диалоговое окно просто отображает сообщение об ошибке для конечного пользователя и дает ему способы связаться с нами.

Вот мой глобальный обработчик ...

import { ErrorHandler, Injectable, Injector } from '@angular/core';
import {
  HttpErrorResponse,
  HttpHeaders,
  HttpClient
} from '@angular/common/http';
import { LocationStrategy, PathLocationStrategy } from '@angular/common';
import { throwError } from 'rxjs';
import * as StackTrace from 'stacktrace-js';
import { LoggerService } from '../core/logger.service';
import { ErrorService } from '../core/error.service';
import { MatDialog } from '@angular/material';
import { ErrorDialogComponent } from './error-dialog.component';
import { ConfigService } from '../app-config.service';

@Injectable({
  providedIn: 'root'
})
/**
 * GlobalErrorHandler to grab errors and log them
 */
export class GlobalErrorHandler implements ErrorHandler {
  /**
   * constructor to inject
   */
  constructor(private injector: Injector, public dialog: MatDialog) {}
  /**
   * Function to handle errors
   *
   * @param (error) error passed to function
   */
  handleError(error: Error) {
    console.log('error (global): ', error);
    const errorService = this.injector.get(ErrorService);
    const logger = this.injector.get(LoggerService);
    const location = this.injector.get(LocationStrategy);
        // Message variable to hold error message
    let errorMessage;
    // Variable to hold url location of error
    const url = location instanceof PathLocationStrategy ? location.path() : '';
    console.log('url: ', url);
    // check if error is a client error
    if (error instanceof Error) {
      // Client error message from error service
      errorMessage = errorService.getClientMessage(error);
      // Open dialog and display error message
      this.openDialog(errorMessage);
    }
    // get the stack trace, lets grab the last 10 stacks only
    StackTrace.fromError(error).then(stackframes => {
      const stackString = stackframes
        .splice(0, 20)
        .map(function(sf) {
          return sf.toString();
        })
        .join();
      /**
       * Function to log errors to api and mantis
       *
       * @param (errorMessage) error message passed to function
       * @param (url) url passed to function
       * @param (stackString) stackString passed to function
       */
      logger.createErrorLog(errorMessage, url, stackString).subscribe(
        result => {
          console.log('log filed');
        },
        (err: any) => console.log(err)
      );
    });
    return throwError(error);
  }
  /**
   * Function to open dialog to display error
   *
   * @param (data) error data to display
   */
  openDialog(data): void {
    const dialogRef = this.dialog.open(ErrorDialogComponent, {
      width: '60%',
      data: data
    });
    // Code to run after the dialog is closed
    dialogRef.afterClosed().subscribe(result => {
      // Redirect back to home (dashboard)?
    });
  }
}

Так есть способ перехватить 404 код и выполнить перенаправление, но не вызывать глобальный обработчик ошибок?

1 Ответ

1 голос
/ 20 февраля 2020

Мне удалось это исправить с помощью Z.Bagley и ссылки, которой он поделился. Я заметил, что мне не хватает вызова next.handle ().

Вот мой исправленный код перехватчика ...

if (error.status === 404) { 
    const newRequest = request.clone();
    return next.handle(newRequest); 
} 
...