第一部分: http://www.cnblogs.com/cgzl/p/8478993.htmlhtml
第二部分: http://www.cnblogs.com/cgzl/p/8481825.htmlweb
第三部分: http://www.javashuo.com/article/p-gzeutreg-cg.html面試
這篇文章將介紹angular 5的全局錯誤處理.ajax
須要使用到代碼: https://pan.baidu.com/s/1F0KjbwVE8_Tzfwy69Alp-Abootstrap
參考文檔: https://angular.io/api/core/ErrorHandler後端
首先按照文檔在客戶端項目創建app.error-handler.ts 文件:api
import { ErrorHandler } from '@angular/core'; export class AppErrorHandler implements ErrorHandler { handleError(error: any): void { console.log('ERROR Occurred.'); } }
這裏, 咱們只寫log.瀏覽器
而後在app.module裏面註冊:app
providers: [
TvNetworkService,
{ provide: ErrorHandler, useClass: AppErrorHandler }
],
而後把tv-network-list.component.ts裏面到一個錯誤處理刪除掉:asp.net
而後在後端到Controller裏面拋一個異常:
而後咱們試一下:
能夠看到, 這個全局錯誤處理器正常到工做了.
先別急, 讓咱們在errorhandler裏面使用toastr試試.
app.error-handler.ts:
import { ErrorHandler } from '@angular/core'; import { ToastrService } from 'ngx-toastr'; export class AppErrorHandler implements ErrorHandler { constructor(private toastr: ToastrService) { } handleError(error: any): void { // console.log('ERROR Occurred.'); this.toastr.error('發生了錯誤'); } }
而這時回到瀏覽器以後, 發生了錯誤:
之因此發生這個錯誤, 是由於AppErrorHandler在angular引入Toastr模塊以前就初始化了.
咱們能夠這樣處理:
import { ErrorHandler, Injectable, Injector, Inject } from '@angular/core'; import { ToastrService, Toast } from 'ngx-toastr'; @Injectable() export class AppErrorHandler implements ErrorHandler { constructor(private injector: Injector) { } private get toastr(): ToastrService { return this.injector.get(ToastrService); } handleError(error: any): void { this.toastr.error('發生了錯誤'); } }
使用Injector來手動注入ToastrService.
回到瀏覽器:
並無彈出錯誤信息!!!!, 可是來回切換菜單後, 開始顯示錯誤信息了, 貌似有點遲鈍.
這是什麼緣由呢? 首先, 咱們得了解如下這個東西:
首先到首先, 須要瞭解如下execution context, 程序執行到上下文, 可是這些東西到定義看了以後可能會讓人迷糊. 因此仍是先看這段代碼吧:
const Zone = { run: (callback) => { if (this.beforeTask) { this.beforeTask(); } callback(); if (this.afterTask) { this.afterTask(); } } }; Zone.beforeTask = () => { console.log('Before Task.'); }; Zone.afterTask = () => { console.log('After Task.'); }; Zone.run(() => { console.log('Running...'); });
就是定義一個Zone, 它到run方法能夠執行某個回調函數, 回調函數到先後還能夠有一些預約義的函數, 若是它們存在就會被執行. 經過定義這些函數的內容, 咱們就能夠在執行run的回調先後添加自定義邏輯了.
回到Angular, angular的變化檢測(Change Detection)功能就用到了這些東西.
好比angular的一個component有一個click事件, click()方法裏更新了某些屬性的值, 這個時候angular就須要進行變化檢測, 若是真的發生了變化, 那麼angular 就會更新dom, 這樣咱們就能看見頁面的變化了. Angular用了這個猴子補丁, 使之運行在Zone裏面, 當點擊按鈕的時候, 這段代碼老是在Zone裏面執行, 在執行完click處理方法以後, angular會執行變化檢測動做.
angular應該是這樣來進行猴子補丁的:
const Zone = { run: (callback) => { if (this.beforeTask) { this.beforeTask(); } callback(); if (this.afterTask) { this.afterTask(); } } }; Zone.beforeTask = () => { console.log('Before Task.'); }; Zone.afterTask = () => { console.log('After Task.'); }; Zone.run(() => { console.log('Running...'); }); var _setTimeout = setTimeout; setTimeout = (callback, timeout) => { Zone.run(() => { _setTimeout(callback, timeout); }); }; click(() => { console.log('設置Timeout'); });
因爲這個是異步的, 因此打印到控制檯到順序多是: Before Task, After Task, 設置Timeout.
js運行時裏, 有一個信息隊列. 任什麼時候候出現一個異步操做, 隊列裏就會推動去一條信息, js運行時會訓話這個隊列, 一個個把消息推出隊列, 而後調用這個消息到回調函數. 對於這個例子來講就是setTimeout().
因此就出現了Zone.js這個庫.
Zone.js就是一個執行的上下文, 它能夠在不一樣的異步操做之間進行持久性傳遞.
Angular就使用了這個庫, 在它之上創建了ngZone這個模塊. 就這樣angular在發生異步操做後進行到了變化檢測.
瀏覽器裏面主要有這幾種異步操做: dom事件, ajax請求, 定時回調之類的.
回到項目裏的app.error-handler.ts:
這句話呢就跑出了angular zone的範圍...
因此當錯誤發生的時候, toastr的error方法被調用了(狀態改變了), 可是angular並不知道這個變化, 因此toastr通知沒有顯示.
那如何解決呢?
使用ngZone:
import { ErrorHandler, Injectable, Injector, Inject, NgZone } from '@angular/core'; import { ToastrService, Toast } from 'ngx-toastr'; @Injectable() export class AppErrorHandler implements ErrorHandler { constructor( private injector: Injector, private ngZone: NgZone ) { } private get toastr(): ToastrService { return this.injector.get(ToastrService); } handleError(error: any): void { this.ngZone.run(() => { this.toastr.error('發生了錯誤'); }); } }
下面試試頁面:
此次沒有任何問題了.
您能夠本身寫一個後臺api來記錄日誌, 可是這裏我介紹一個專門作logging的雲服務, sentry.io. https://sentry.io/
首先請您本身註冊帳戶.
而後建立一個項目, 選擇angular:
而後點擊下面按鈕Create Project.
而後它給出了安裝和配置的說明:
首先執行命令安裝.
而後, 配置:
import * as Raven from 'raven-js'; import { BrowserModule } from '@angular/platform-browser'; import { NgModule, ErrorHandler } from '@angular/core'; import { AppComponent } from './app.component'; Raven .config('https://fa66d9390ab04c7f8e8c82ad0613fb4e@sentry.io/301095') .install(); @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ], providers: [ { provide: ErrorHandler, useClass: AppErrorHandler } ] }) export class AppModule { }
按照說明進行配置, 咱們作一些調整, 這裏紅色部分是每一個用戶都不同都.
最後修改app.error-handler.ts:
import { ErrorHandler, Injectable, Injector, Inject, NgZone } from '@angular/core'; import { ToastrService, Toast } from 'ngx-toastr'; import * as Raven from 'raven-js'; @Injectable() export class AppErrorHandler implements ErrorHandler { constructor( private injector: Injector, private ngZone: NgZone ) { } private get toastr(): ToastrService { return this.injector.get(ToastrService); } handleError(error: any): void { Raven.captureException(error); this.ngZone.run(() => { this.toastr.error('發生了錯誤'); }); } }
回到瀏覽器的錯誤頁面, 觸發錯誤後, 大約幾分鐘後, 來到sentry.io網站查看:
今天先寫到這, 明天后天寫如下 angular5上傳文件到asp.net core web api.