寫在前面
代碼寫得再好,始終都無法完整的處理所有可能產(chǎn)生異常,特別是生產(chǎn)環(huán)境中的應(yīng)用莽鸭,很大一部分是數(shù)據(jù)來自用戶、遠(yuǎn)程珠移,很難保證所有數(shù)據(jù)都按程序規(guī)定的產(chǎn)生。事實(shí)上,除非測試人員發(fā)現(xiàn)或者客戶報(bào)告钧惧,否則都無法得知暇韧。因此,將應(yīng)用產(chǎn)生的未可知異常進(jìn)而上報(bào)是非常重要的環(huán)節(jié)浓瞪。
Angular 默認(rèn)情況下也提供了全局的異常管理懈玻,當(dāng)發(fā)生異常時(shí),會(huì)把它扔到 Console 控制臺(tái)上乾颁。如果你在使用 NG-ZORRO 時(shí)涂乌,可能經(jīng)常就會(huì)遇到 ICON 未加載的異常消息,這也是異常消息的一種:
core.js:5980 ERROR Error: [@ant-design/icons-angular]:the icon setting-o does not exist or is not registered.
at IconNotFoundError (ant-design-icons-angular.js:94)
at MapSubscriber.project (ant-design-icons-angular.js:222)
at MapSubscriber._next (map.js:29)
at MapSubscriber.next (Subscriber.js:49)
at RefCountSubscriber._next (Subscriber.js:72)
at RefCountSubscriber.next (Subscriber.js:49)
at Subject.next (Subject.js:39)
at ConnectableSubscriber._next (Subscriber.js:72)
at ConnectableSubscriber.next (Subscriber.js:49)
at CatchSubscriber.notifyNext (innerSubscribe.js:42)
而 Angular 是通過 ErrorHandler 統(tǒng)一管理異常消息英岭,而且只需要覆蓋其中的 handleError
方法并重新處理異常消息即可湾盒。
ErrorHandler
首先創(chuàng)建一個(gè) custom-error-handler.ts
文件:
import { ErrorHandler, Injectable } from '@angular/core';
@Injectable()
export class CustomErrorHandler extends ErrorHandler {
handleError(error: any): void {
super.handleError(error);
}
}
CustomErrorHandler
可以完整的獲取當(dāng)前用戶數(shù)據(jù)、當(dāng)前異常消息對象等诅妹,并允許通過 HttpClient
上報(bào)給后端罚勾。
以下是 NG-ALAIN 的文檔站,由于是使用 Google Analytics 來分析吭狡,只需要將異常消息轉(zhuǎn)給 onerror
即可:
import { DOCUMENT } from '@angular/common';
import { ErrorHandler, Inject, Injectable } from '@angular/core';
@Injectable()
export class CustomErrorHandler extends ErrorHandler {
constructor(@Inject(DOCUMENT) private doc: any) {
super();
}
handleError(error: any): void {
try {
super.handleError(error);
} catch (e) {
this.reportError(e);
}
this.reportError(error);
}
private reportError(error: string | Error): void {
const win = this.doc.defaultView as any;
if (win && win.onerror) {
if (typeof error === 'string') {
win.onerror(error);
} else {
win.onerror(error.message, undefined, undefined, undefined, error);
}
}
}
}
最后尖殃,在 AppModule
模塊內(nèi)注冊 CustomErrorHandler
:
@NgModule({
providers: [
{ provide: ErrorHandler, useClass: CustomErrorHandler },
]
})
export class AppModule { }
結(jié)論
事實(shí)上還有一項(xiàng)非常重要的工作,生產(chǎn)環(huán)境中都是打包壓縮過后的划煮,換言之所產(chǎn)生的異常消息也是無法與實(shí)際代碼行數(shù)相同的數(shù)字送丰,這就需要 SourceMap 的支持,當(dāng)然正常的生產(chǎn)環(huán)境是不會(huì)發(fā)布這份文件的弛秋,所以如果想要得到正確的行列數(shù)器躏,還是需要借助一層中間層,在后端利用 source-map 模塊來解析出真正的行列數(shù)值铐懊。
Angular 的依賴注入(DI)系統(tǒng)可以使我們快速替換一些 Angular 內(nèi)置模塊邀桑,從而實(shí)現(xiàn)在不修改業(yè)務(wù)層面時(shí)快速解決一些特殊需求。
(完)