這篇文章帶大家深入了解一下Angular中常用的錯誤處理方式,希望對大家有幫助!
錯誤處理是編寫程式碼經常遇見的並且必須處理的需求,很多時候處理異常的邏輯是為了避免程式的崩潰,本文將簡單介紹Angular
處理異常的方式。 【相關教學推薦:《angular教學》】
Angualr
是一款來自Google的開源的web 前端框架,誕生於2009 年,由Misko Hevery 等人創建,後來由Google 所收購。是一款優秀的前端 JS 框架,已經被用於 Google 的多款產品當中。
AngularJS 是基於聲明式程式設計模式是使用者可以基於業務邏輯進行開發. 該框架基於HTML的內容填充並做了雙向資料綁定從而完成了自動資料同步機制. 最後, AngularJS強化的DOM操作增強了可測試性.
最熟悉的方式,就是在程式碼中加入try/ catch
區塊,在try
中發生錯誤,就會被捕獲並且讓腳本繼續執行。然而,隨著應用程式規模的擴大,這種方式將變得無法管理。
Angular
提供了一個預設的ErrorHandler
,可以將錯誤訊息列印到控制台,因此可以攔截這個預設行為來添加自訂的處理邏輯,下面嘗試編寫錯誤處理類別:
import { ErrorHandler, Injectable } from "@angular/core"; import { HttpErrorResponse } from "@angular/common/http"; @Injectable() export class ErrorsHandler implements ErrorHandler { handleError(error: Error | HttpErrorResponse) { if (!navigator.onLine) { console.error("Browser Offline!"); } else { if (error instanceof HttpErrorResponse) { if (!navigator.onLine) { console.error("Browser Offline!"); } else { // Handle Http Error (4xx, 5xx, ect.) console.error("Http Error!"); } } else { // Handle Client Error (Angular Error, ReferenceError...) console.error("Client Error!"); } console.error(error); } } }
#通常在
app
#下建立一個共享目錄shared
,並將此檔案放在providers
資料夾中
現在,需要更改應用程式的預設行為,以使用我們自訂的類別而不是ErrorHandler
。修改app.module.ts
文件,從@angular/core
導入ErrorHandler
,並將providers
添加到@NgModule
模組,程式碼如下:
import { NgModule, ErrorHandler } from "@angular/core"; import { BrowserModule } from "@angular/platform-browser"; import { FormsModule } from "@angular/forms"; // Providers import { ErrorsHandler } from "./shared/providers/error-handler"; import { AppComponent } from "./app.component"; @NgModule({ imports: [BrowserModule, FormsModule], declarations: [AppComponent], providers: [{ provide: ErrorHandler, useClass: ErrorsHandler }], bootstrap: [AppComponent] }) export class AppModule {}
#HttpInterceptor
提供了一種攔截HTTP請求/回應的方法,就可以在傳遞它們之前處理。例如,可以在拋出錯誤之前重試幾次HTTP請求。這樣,就可以優雅地處理超時,而不必拋出錯誤。
還可以在拋出錯誤之前檢查錯誤的狀態,使用攔截器,可以檢查401狀態錯誤碼,將使用者重新導向到登入頁面。
import { Injectable } from "@angular/core"; import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor, HttpErrorResponse } from "@angular/common/http"; import { Observable, throwError } from "rxjs"; import { retry, catchError } from "rxjs/operators"; @Injectable() export class HttpsInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(request).pipe( retry(1), catchError((error: HttpErrorResponse) => { if (error.status === 401) { // 跳转到登录页面 } else { return throwError(error); } }) ); } }
同樣需要添加到app.module.ts
中
import { NgModule, ErrorHandler } from "@angular/core"; import { HTTP_INTERCEPTORS } from "@angular/common/http"; import { BrowserModule } from "@angular/platform-browser"; import { FormsModule } from "@angular/forms"; // Providers import { ErrorsHandler } from "./shared/providers/error-handler"; import { HttpsInterceptor } from "./shared/providers/http-interceptor"; import { AppComponent } from "./app.component"; @NgModule({ imports: [BrowserModule, FormsModule], declarations: [AppComponent], providers: [ { provide: ErrorHandler, useClass: ErrorsHandler }, { provide: HTTP_INTERCEPTORS, useClass: HttpsInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule {}
多提供者用於建立可擴展服務,其中系統帶有一些預設提供者,也可以註冊其他提供者。預設提供者和其他提供者的組合將用於驅動系統的行為。
在控制台列印錯誤日誌對於開發者來說非常友好,但是對於使用者來說則需要一種更加友好的方式來告訴這些錯誤何時從GUI發生。根據錯誤類型,推薦兩個元件:Snackbar
和Dialog
#Snackbar
:推薦用於簡單的提示,例如表單缺少必填欄位或通知使用者可預見的錯誤(無效電子郵件、使用者名稱太長等)。
Dialog
:當存在未知的伺服器端或客戶端錯誤時,建議使用這種方式;透過這種方式,可以顯示更多的描述,甚至call-to-action
,例如允許用戶輸入他們的電子郵件來追蹤錯誤。
在shared
資料夾中新增一個服務來處理所有通知,新建services
資料夾,建立檔案:notification. service.ts
,程式碼如下:
import { Injectable } from "@angular/core"; import { MatSnackBar } from "@angular/material/snack-bar"; @Injectable({ providedIn: "root" }) export class NotificationService { constructor(public snackBar: MatSnackBar) {} showError(message: string) { this.snackBar.open(message, "Close", { panelClass: ["error"] }); } }
更新error-handler.ts
,新增NotificationService
:
import { ErrorHandler, Injectable, Injector } from "@angular/core"; import { HttpErrorResponse } from "@angular/common/http"; // Services import { NotificationService } from "../services/notification.service"; @Injectable() export class ErrorsHandler implements ErrorHandler { //Error handling需要先加载,使用Injector手动注入服务 constructor(private injector: Injector) {} handleError(error: Error | HttpErrorResponse) { const notifier = this.injector.get(NotificationService); if (!navigator.onLine) { //console.error("Browser Offline!"); notifier.showError("Browser Offline!"); } else { if (error instanceof HttpErrorResponse) { if (!navigator.onLine) { //console.error("Browser Offline!"); notifier.showError(error.message); } else { // Handle Http Error (4xx, 5xx, ect.) // console.error("Http Error!"); notifier.showError("Http Error: " + error.message); } } else { // Handle Client Error (Angular Error, ReferenceError...) // console.error("Client Error!"); notifier.showError(error.message); } console.error(error); } } }
如果在一個元件中拋出一個錯誤,可以看到一個很好的snackbar
訊息:
當然不能期望使用者向報告每個bug
,一旦部署到生產環境中,就不能看到任何控制台日誌。因此就需要能夠記錄錯誤的後端服務與自訂邏輯寫入資料庫或使用現有的解決方案,如Rollbar
、Sentry
、Bugsnag
。
接下來建立一個簡單的錯誤追蹤服務,建立logging.service.ts
:
import { Injectable } from "@angular/core"; import { HttpErrorResponse } from "@angular/common/http"; @Injectable({ providedIn: "root" }) export class LoggingService { constructor() {} logError(error: Error | HttpErrorResponse) { // This will be replaced with logging to either Rollbar, Sentry, Bugsnag, ect. if (error instanceof HttpErrorResponse) { console.error(error); } else { console.error(error); } } }
將服務加入error-handler.ts
中:
import { ErrorHandler, Injectable, Injector } from "@angular/core"; import { HttpErrorResponse } from "@angular/common/http"; // Services import { NotificationService } from "../services/notification.service"; import { LoggingService } from "../services/logging.service"; @Injectable() export class ErrorsHandler implements ErrorHandler { //Error handling需要先加载,使用Injector手动注入服务 constructor(private injector: Injector) {} handleError(error: Error | HttpErrorResponse) { const notifier = this.injector.get(NotificationService); const logger = this.injector.get(LoggingService); if (!navigator.onLine) { //console.error("Browser Offline!"); notifier.showError("Browser Offline!"); } else { if (error instanceof HttpErrorResponse) { if (!navigator.onLine) { //console.error("Browser Offline!"); notifier.showError(error.message); } else { // Handle Http Error (4xx, 5xx, ect.) // console.error("Http Error!"); notifier.showError("Http Error: " + error.message); } } else { // Handle Client Error (Angular Error, ReferenceError...) // console.error("Client Error!"); notifier.showError(error.message); } // console.error(error); logger.logError(error); } } }
至此,整個錯誤處理的機制已經介紹完了,基本上跟其他框架或語言開發的專案處理方式類似。
更多程式相關知識,請造訪:程式設計影片! !
以上是聊聊Angular中常用的錯誤處理方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!