Angular 오류 처리
                                            
                                                
                                                
                                                
                                                
                                                
                                                 17849 단어  Angular
                    
나누? 에라 응? ?
시라나 커터 .....
라고 하는 것으로 에러 핸들링에 대해 조사한 것을 메모해 둡니다.
환경
런타임 JS 오류 잡기
ErrorHandler를 상속한 클래스를 구현합니다.
// src/app/custom-error-handler.ts
import { ErrorHandler } from '@angular/core';
export class CustomErrorHandler implements ErrorHandler {
  handleError(e) {
    console.warn('👹ErrorHandler👹', e);
  }
}
클래스를 AppModule 의 providers 로 제공합니다.
import { ErrorHandler } from '@angular/core';
import { CustomErrorHandler } from './custom-error-handler';
@NgModule({
  declarations: [ AppComponent ],
  imports: [ BrowserModule ],
  providers: [
    {
      provide: ErrorHandler,
      useClass: CustomErrorHandler, // これ
    },
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
버튼을 설치하여 일부러 런타임 오류를 발생시킵니다.
// app.component.html
<button (click)="test()">test</button>
// app.component.ts
export class AppComponent implements OnInit {
  test() {
    // TypeError: Cannot read property 'id' of undefined
    return [].find(_ => false).id;
  }
}
커스텀의 ErrorHandler 가 런타임의 JS 에러를 캐치하고 있는 것을 알 수 있습니다.
 
 500 페이지로 이동
오류를 잡은 후 "예기치 않은 오류가 발생했습니다."페이지로 건너 뛰고 싶을 수도 있습니다.
그 경우는 이렇게 구현하면 좋을 것 같습니다.
// src/app/custom-error-handler.ts
// コンストラクタにインジェクトするため Injectable を宣言
@Injectable()
export class CustomErrorHandler implements ErrorHandler {
  constructor(
    private router: Router,
    private zone: NgZone,
  ) {}
  handleError(e) {
    console.warn('👹ErrorHandler👹', e);
    this.zone.run(() => {
      // URLに "/500" を表示せず画面遷移する
      this.router.navigate(['/500'], { skipLocationChange: true });
    });
  }
}
 HTTP 오류 잡기
HttpInterceptor 를 상속한 클래스를 구현합니다.
// src/app/custom-interceptor.ts
import { HttpInterceptor } from '@angular/common/http';
@Injectable()
export class CustomInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler,
  ): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      catchError((e) => {
        console.warn('👹HttpInterceptor👹', e);
        // 呼び出し元で catchError() できるように例外処理
        return throwError(e);
      }),
    );
  }
}
클래스를 AppModule 의 providers 로 제공합니다.
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { CustomInterceptor } from './custom-interceptor.ts';
@NgModule({
  declarations: [ AppComponent ],
  imports: [ BrowserModule, HttpClientModule ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: CustomInterceptor, // これ
      multi: true,
    }
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
버튼을 설치하여 일부러 에러를 발생시켜 봅시다.
// app.component.html
<button (click)="test2()">test2</button>
// app.component.ts
export class AppComponent implements OnInit {
  test2() {
    // 存在しない URL へのリクエスト
    this.http.get(
      'http://dummy.restapiexample.com/api/v1/dummy-request',
    ).pipe(
      catchError(() => EMPTY)
    ).subscribe();
  }
}
사용자 정의 Intercepter가 HTTP 오류를 포착하고 있음을 알 수 있습니다.
 
 라우터 오류 잡기
Router의 errorHandler를 변경합니다.
// app.component.ts
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  constructor(
    private router: Router,
  ) {}
  ngOnInit() {
    this.router.errorHandler = (e) => {
      console.warn('👹router ErrorHandler👹', e);
      this.router.navigate(['/403'], { skipLocationChange: true });
    };
  }
※ errorHandler 를 어디에서 세트 하는 것이 올바른지, 정보가 발견되지 않았기 때문에 우선 AppComponent.ngOnInit 로 선언했습니다.
앵커 태그를 설치하고 일부러 존재하지 않는 페이지로의 전환을 생성해 봅시다.
// app.component.html
<a routerLink="/path/to/invalid">invalid</a>
router.errorHandler가 존재하지 않는 페이지로의 전환을 포착하고 있음을 알 수 있습니다.
 
또한, 톱 페이지로 리디렉션하는 폴백을 지정하고 있는 경우는, 라우터의 errorHandler 는 실행되지 않습니다.
// app-router.module.ts
const routes: Routes = [
  { ... },
  { // リダイレクトによりエラーが発生しない
    path: '**',
    pathMatch: 'full',
    redirectTo: '',
  }
];
@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ],
})
export class AppRouterModule {}
 끝
Angular의 에러 핸들링을 이용하면 쉽게 에러를 잡을 수 있네요. 샘플의 코드에서는 console.warn 하고 있을 뿐입니다만, 실제의 운영에서는 로그 수집 서비스에 에러 정보를 던지는 등, 여러가지 유효 활용할 수 있을 것 같습니다.
                
                    
        
    
    
    
    
    
                
                
                
                
                    
                        
                            
                            
                            Reference
                            
                            이 문제에 관하여(Angular 오류 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
                                
                                https://qiita.com/ringtail003/items/2229c0ad1697a26cac02
                            
                            
                            
                                텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                            
                            
                                
                                
                                 우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                            
                            
                        
                    
                
                
                
            
// src/app/custom-error-handler.ts
import { ErrorHandler } from '@angular/core';
export class CustomErrorHandler implements ErrorHandler {
  handleError(e) {
    console.warn('👹ErrorHandler👹', e);
  }
}
import { ErrorHandler } from '@angular/core';
import { CustomErrorHandler } from './custom-error-handler';
@NgModule({
  declarations: [ AppComponent ],
  imports: [ BrowserModule ],
  providers: [
    {
      provide: ErrorHandler,
      useClass: CustomErrorHandler, // これ
    },
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
// app.component.html
<button (click)="test()">test</button>
// app.component.ts
export class AppComponent implements OnInit {
  test() {
    // TypeError: Cannot read property 'id' of undefined
    return [].find(_ => false).id;
  }
}
오류를 잡은 후 "예기치 않은 오류가 발생했습니다."페이지로 건너 뛰고 싶을 수도 있습니다.
그 경우는 이렇게 구현하면 좋을 것 같습니다.
// src/app/custom-error-handler.ts
// コンストラクタにインジェクトするため Injectable を宣言
@Injectable()
export class CustomErrorHandler implements ErrorHandler {
  constructor(
    private router: Router,
    private zone: NgZone,
  ) {}
  handleError(e) {
    console.warn('👹ErrorHandler👹', e);
    this.zone.run(() => {
      // URLに "/500" を表示せず画面遷移する
      this.router.navigate(['/500'], { skipLocationChange: true });
    });
  }
}
HTTP 오류 잡기
HttpInterceptor 를 상속한 클래스를 구현합니다.
// src/app/custom-interceptor.ts
import { HttpInterceptor } from '@angular/common/http';
@Injectable()
export class CustomInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler,
  ): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      catchError((e) => {
        console.warn('👹HttpInterceptor👹', e);
        // 呼び出し元で catchError() できるように例外処理
        return throwError(e);
      }),
    );
  }
}
클래스를 AppModule 의 providers 로 제공합니다.
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { CustomInterceptor } from './custom-interceptor.ts';
@NgModule({
  declarations: [ AppComponent ],
  imports: [ BrowserModule, HttpClientModule ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: CustomInterceptor, // これ
      multi: true,
    }
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
버튼을 설치하여 일부러 에러를 발생시켜 봅시다.
// app.component.html
<button (click)="test2()">test2</button>
// app.component.ts
export class AppComponent implements OnInit {
  test2() {
    // 存在しない URL へのリクエスト
    this.http.get(
      'http://dummy.restapiexample.com/api/v1/dummy-request',
    ).pipe(
      catchError(() => EMPTY)
    ).subscribe();
  }
}
사용자 정의 Intercepter가 HTTP 오류를 포착하고 있음을 알 수 있습니다.
 
 라우터 오류 잡기
Router의 errorHandler를 변경합니다.
// app.component.ts
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  constructor(
    private router: Router,
  ) {}
  ngOnInit() {
    this.router.errorHandler = (e) => {
      console.warn('👹router ErrorHandler👹', e);
      this.router.navigate(['/403'], { skipLocationChange: true });
    };
  }
※ errorHandler 를 어디에서 세트 하는 것이 올바른지, 정보가 발견되지 않았기 때문에 우선 AppComponent.ngOnInit 로 선언했습니다.
앵커 태그를 설치하고 일부러 존재하지 않는 페이지로의 전환을 생성해 봅시다.
// app.component.html
<a routerLink="/path/to/invalid">invalid</a>
router.errorHandler가 존재하지 않는 페이지로의 전환을 포착하고 있음을 알 수 있습니다.
 
또한, 톱 페이지로 리디렉션하는 폴백을 지정하고 있는 경우는, 라우터의 errorHandler 는 실행되지 않습니다.
// app-router.module.ts
const routes: Routes = [
  { ... },
  { // リダイレクトによりエラーが発生しない
    path: '**',
    pathMatch: 'full',
    redirectTo: '',
  }
];
@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ],
})
export class AppRouterModule {}
 끝
Angular의 에러 핸들링을 이용하면 쉽게 에러를 잡을 수 있네요. 샘플의 코드에서는 console.warn 하고 있을 뿐입니다만, 실제의 운영에서는 로그 수집 서비스에 에러 정보를 던지는 등, 여러가지 유효 활용할 수 있을 것 같습니다.
                
                    
        
    
    
    
    
    
                
                
                
                
                    
                        
                            
                            
                            Reference
                            
                            이 문제에 관하여(Angular 오류 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
                                
                                https://qiita.com/ringtail003/items/2229c0ad1697a26cac02
                            
                            
                            
                                텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                            
                            
                                
                                
                                 우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                            
                            
                        
                    
                
                
                
            
// src/app/custom-interceptor.ts
import { HttpInterceptor } from '@angular/common/http';
@Injectable()
export class CustomInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler,
  ): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      catchError((e) => {
        console.warn('👹HttpInterceptor👹', e);
        // 呼び出し元で catchError() できるように例外処理
        return throwError(e);
      }),
    );
  }
}
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { CustomInterceptor } from './custom-interceptor.ts';
@NgModule({
  declarations: [ AppComponent ],
  imports: [ BrowserModule, HttpClientModule ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: CustomInterceptor, // これ
      multi: true,
    }
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
// app.component.html
<button (click)="test2()">test2</button>
// app.component.ts
export class AppComponent implements OnInit {
  test2() {
    // 存在しない URL へのリクエスト
    this.http.get(
      'http://dummy.restapiexample.com/api/v1/dummy-request',
    ).pipe(
      catchError(() => EMPTY)
    ).subscribe();
  }
}
Router의 errorHandler를 변경합니다.
// app.component.ts
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  constructor(
    private router: Router,
  ) {}
  ngOnInit() {
    this.router.errorHandler = (e) => {
      console.warn('👹router ErrorHandler👹', e);
      this.router.navigate(['/403'], { skipLocationChange: true });
    };
  }
※ errorHandler 를 어디에서 세트 하는 것이 올바른지, 정보가 발견되지 않았기 때문에 우선 AppComponent.ngOnInit 로 선언했습니다.
앵커 태그를 설치하고 일부러 존재하지 않는 페이지로의 전환을 생성해 봅시다.
// app.component.html
<a routerLink="/path/to/invalid">invalid</a>
router.errorHandler가 존재하지 않는 페이지로의 전환을 포착하고 있음을 알 수 있습니다.

또한, 톱 페이지로 리디렉션하는 폴백을 지정하고 있는 경우는, 라우터의 errorHandler 는 실행되지 않습니다.
// app-router.module.ts
const routes: Routes = [
  { ... },
  { // リダイレクトによりエラーが発生しない
    path: '**',
    pathMatch: 'full',
    redirectTo: '',
  }
];
@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ],
})
export class AppRouterModule {}
끝
Angular의 에러 핸들링을 이용하면 쉽게 에러를 잡을 수 있네요. 샘플의 코드에서는 console.warn 하고 있을 뿐입니다만, 실제의 운영에서는 로그 수집 서비스에 에러 정보를 던지는 등, 여러가지 유효 활용할 수 있을 것 같습니다.
                
                    
        
    
    
    
    
    
                
                
                
                
                    
                        
                            
                            
                            Reference
                            
                            이 문제에 관하여(Angular 오류 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
                                
                                https://qiita.com/ringtail003/items/2229c0ad1697a26cac02
                            
                            
                            
                                텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                            
                            
                                
                                
                                 우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                            
                            
                        
                    
                
                
                
            
Reference
이 문제에 관하여(Angular 오류 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ringtail003/items/2229c0ad1697a26cac02텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)