第一部分: 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.