第一部分: http://www.cnblogs.com/cgzl/p/8478993.html

第二部分: http://www.cnblogs.com/cgzl/p/8481825.html

第三部分: https://www.cnblogs.com/cgzl/p/8525541.html

这篇文章将介绍angular 5的全局错误处理.

需要使用到代码: https://pan.baidu.com/s/1F0KjbwVE8_Tzfwy69Alp-A

angular 5 全局错误处理

参考文档: https://angular.io/api/core/ErrorHandler

首先按照文档在客户端项目建立app.error-handler.ts 文件:

  1. import { ErrorHandler } from '@angular/core';
  2.  
  3. export class AppErrorHandler implements ErrorHandler {
  4. handleError(error: any): void {
  5. console.log('ERROR Occurred.');
  6. }
  7. }

这里, 我们只写log.

然后在app.module里面注册:

  1. providers: [
  2. TvNetworkService,
  3. { provide: ErrorHandler, useClass: AppErrorHandler }
  4. ],

然后把tv-network-list.component.ts里面到一个错误处理删除掉:

然后在后端到Controller里面抛一个异常:

然后我们试一下:

可以看到, 这个全局错误处理器正常到工作了.

先别急, 让我们在errorhandler里面使用toastr试试.

app.error-handler.ts:

  1. import { ErrorHandler } from '@angular/core';
  2. import { ToastrService } from 'ngx-toastr';
  3.  
  4. export class AppErrorHandler implements ErrorHandler {
  5.  
  6. constructor(private toastr: ToastrService) { }
  7.  
  8. handleError(error: any): void {
  9. // console.log('ERROR Occurred.');
  10. this.toastr.error('发生了错误');
  11. }
  12. }

而这时回到浏览器之后, 发生了错误:

之所以发生这个错误, 是因为AppErrorHandler在angular引入Toastr模块之前就初始化了.

我们可以这样处理:

  1. import { ErrorHandler, Injectable, Injector, Inject } from '@angular/core';
  2. import { ToastrService, Toast } from 'ngx-toastr';
  3.  
  4. @Injectable()
  5. export class AppErrorHandler implements ErrorHandler {
  6.  
  7. constructor(private injector: Injector) { }
  8.  
  9. private get toastr(): ToastrService {
  10. return this.injector.get(ToastrService);
  11. }
  12.  
  13. handleError(error: any): void {
  14. this.toastr.error('发生了错误');
  15. }
  16. }

使用Injector来手动注入ToastrService.

回到浏览器:

并没有弹出错误信息!!!!, 但是来回切换菜单后, 开始显示错误信息了, 貌似有点迟钝.

这是什么原因呢? 首先, 我们得了解以下这个东西:

Zone

首先到首先, 需要了解以下execution context, 程序执行到上下文, 但是这些东西到定义看了之后可能会让人迷糊. 所以还是先看这段代码吧:

  1. const Zone = {
  2. run: (callback) => {
  3. if (this.beforeTask) {
  4. this.beforeTask();
  5. }
  6. callback();
  7. if (this.afterTask) {
  8. this.afterTask();
  9. }
  10. }
  11. };
  12.  
  13. Zone.beforeTask = () => {
  14. console.log('Before Task.');
  15. };
  16. Zone.afterTask = () => {
  17. console.log('After Task.');
  18. };
  19. Zone.run(() => {
  20. console.log('Running...');
  21. });

就是定义一个Zone, 它到run方法可以执行某个回调函数, 回调函数到前后还可以有一些预定义的函数, 如果它们存在就会被执行. 通过定义这些函数的内容, 我们就可以在执行run的回调前后添加自定义逻辑了.

回到Angular, angular的变化检测(Change Detection)功能就用到了这些东西.

比如angular的一个component有一个click事件, click()方法里更新了某些属性的值, 这个时候angular就需要进行变化检测, 如果真的发生了变化, 那么angular 就会更新dom, 这样我们就能看见页面的变化了. Angular用了这个猴子补丁, 使之运行在Zone里面, 当点击按钮的时候, 这段代码总是在Zone里面执行, 在执行完click处理方法之后, angular会执行变化检测动作.

angular应该是这样来进行猴子补丁的:

  1. const Zone = {
  2. run: (callback) => {
  3. if (this.beforeTask) {
  4. this.beforeTask();
  5. }
  6. callback();
  7. if (this.afterTask) {
  8. this.afterTask();
  9. }
  10. }
  11. };
  12.  
  13. Zone.beforeTask = () => {
  14. console.log('Before Task.');
  15. };
  16. Zone.afterTask = () => {
  17. console.log('After Task.');
  18. };
  19. Zone.run(() => {
  20. console.log('Running...');
  21. });
  22.  
  23. var _setTimeout = setTimeout;
  24. setTimeout = (callback, timeout) => {
  25. Zone.run(() => {
  26. _setTimeout(callback, timeout);
  27. });
  28. };
  29. click(() => {
  30. console.log('设置Timeout');
  31. });

由于这个是异步的, 所以打印到控制台到顺序可能是: 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:

  1. import { ErrorHandler, Injectable, Injector, Inject, NgZone } from '@angular/core';
  2. import { ToastrService, Toast } from 'ngx-toastr';
  3.  
  4. @Injectable()
  5. export class AppErrorHandler implements ErrorHandler {
  6.  
  7. constructor(
  8. private injector: Injector,
  9. private ngZone: NgZone
  10. ) { }
  11.  
  12. private get toastr(): ToastrService {
  13. return this.injector.get(ToastrService);
  14. }
  15.  
  16. handleError(error: any): void {
  17. this.ngZone.run(() => {
  18. this.toastr.error('发生了错误');
  19. });
  20. }
  21. }

下面试试页面:

这次没有任何问题了.

Logging Errors 记录错误

您可以自己写一个后台api来记录日志, 但是这里我介绍一个专门做logging的云服务, sentry.iohttps://sentry.io/

首先请您自己注册账户.

然后创建一个项目, 选择angular:

然后点击下面按钮Create Project.

然后它给出了安装和配置的说明:

首先执行命令安装.

然后, 配置:

  1. import * as Raven from 'raven-js';
  2. import { BrowserModule } from '@angular/platform-browser';
  3. import { NgModule, ErrorHandler } from '@angular/core';
  4. import { AppComponent } from './app.component';
  5.  
  6. Raven
  7. .config('https://fa66d9390ab04c7f8e8c82ad0613fb4e@sentry.io/301095')
  8. .install();

  9. @NgModule({
  10. imports: [ BrowserModule ],
  11. declarations: [ AppComponent ],
  12. bootstrap: [ AppComponent ],
  13. providers: [ { provide: ErrorHandler, useClass: AppErrorHandler } ]
  14. })
  15. export class AppModule { }

按照说明进行配置, 我们做一些调整, 这里红色部分是每个用户都不一样都.

最后修改app.error-handler.ts:

  1. import { ErrorHandler, Injectable, Injector, Inject, NgZone } from '@angular/core';
  2. import { ToastrService, Toast } from 'ngx-toastr';
  3. import * as Raven from 'raven-js';
  4.  
  5. @Injectable()
  6. export class AppErrorHandler implements ErrorHandler {
  7.  
  8. constructor(
  9. private injector: Injector,
  10. private ngZone: NgZone
  11. ) { }
  12.  
  13. private get toastr(): ToastrService {
  14. return this.injector.get(ToastrService);
  15. }
  16.  
  17. handleError(error: any): void {
  18. Raven.captureException(error);
  19. this.ngZone.run(() => {
  20. this.toastr.error('发生了错误');
  21. });
  22. }
  23. }

回到浏览器的错误页面, 触发错误后, 大约几分钟后, 来到sentry.io网站查看:

今天先写到这, 明天后天写以下 angular5上传文件到asp.net core web api.

用VSCode开发一个asp.net core 2.0+angular 5项目(4): Angular5全局错误处理的更多相关文章

  1. 使用VS Code开发调试ASP.NET Core 1.0

    使用VS Code开发调试ASP.NET Core 1.0,微软在今天凌晨发布了.NET Core 1.0,ASP.NET Core 1.0 与 Entity Framewok 1.0. 之前跟大家讲 ...

  2. VS Code开发调试ASP.NET Core 1.0

    VS Code开发调试ASP.NET Core 1.0 使用VS Code开发调试ASP.NET Core 1.0,微软在今天凌晨发布了.NET Core 1.0,ASP.NET Core 1.0 与 ...

  3. 用VSCode开发一个asp.net core2.0+angular5项目(5): Angular5+asp.net core 2.0 web api文件上传

    第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 第三 ...

  4. 使用 Asp.net core 2.0 + Angular 4 构建车辆管理的Web应用程序

    https://www.codeproject.com/Articles/1210559/Asp-net-core-Angular-Build-from-scratch-a-web

  5. [译]ASP.NET Core 2.0 中间件

    问题 如何创建一个最简单的ASP.NET Core中间件? 答案 使用VS创建一个ASP.NET Core 2.0的空项目,注意Startup.cs中的Configure()方法: public vo ...

  6. ASP.NET Core 1.0 开发记录

    官方资料: https://github.com/dotnet/core https://docs.microsoft.com/en-us/aspnet/core https://docs.micro ...

  7. 在 Mac OS 上使用 TypeScript 编写 ASP.NET Core 1.0 应用

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  8. Amazing ASP.NET Core 2.0

    前言 ASP.NET Core 的变化和发展速度是飞快的,当你发现你还没有掌握 ASP.NET Core 1.0 的时候, 2.0 已经快要发布了,目前 2.0 处于 Preview 1 版本,意味着 ...

  9. ASP.NET Core 2.0 使用支付宝PC网站支付

    前言 最近在使用ASP.NET Core来进行开发,刚好有个接入支付宝支付的需求,百度了一下没找到相关的资料,看了官方的SDK以及Demo都还是.NET Framework的,所以就先根据官方SDK的 ...

随机推荐

  1. 让XtraMessageBox按钮显示中文

    需要定义一个继承子Localizer的类,然后重写GetLocalizedString public class MessboxClass : Localizer { public override ...

  2. 安卓中圆角背景图被拉伸的解决方案——.9.png

    举个例子: 从网上找了一张图片 如果我们直接用这张蓝色的图来做登录按钮的背景.将这个图片设为背景以后 我们可以发现四个角全部变形了,一点也不美观.针对此问题,我们通过.9图来解决. 首先我们先了解一下 ...

  3. Jmeter_实现操作postgresql数据库

    [环境] ①Jmeter版本:3.2,JDK:1.8: ②postgresql驱动包postgresql-9.3-1103.jdbc4,将该jar包置于..\apache-jmeter-3.2\lib ...

  4. WPF字典集合类ObservableDictionary

    WPF最核心的技术优势之一就是数据绑定.数据绑定,可以通过对数据的操作来更新界面. 数据绑定最经常用到的是ObservableCollection<T> 和 Dictionary<T ...

  5. JS声明对象时属性名加引号与不加引号的问题

    般情况下属性名加引号和不加引号是都可以的,效果是一样的. var obj = { name : '你好', 'age' : 1, }; document.write( obj['name'] + '& ...

  6. ansible实践-1

      不需要安装客户端,通过sshd去通信 基于模块工作,模块可以由任何语言开发 不仅支持命令行使用模块,也支持编写yaml格式的playbook 支持sudo 有提供UI(浏览器图形化)www.ans ...

  7. 浅谈format格式化输出

    什么是format? 相对于基本格式化输出采用"%"的方法,format的功能强大,该函数把字符串当一个模板,通过传入的参数进行格式化,并且使用大括号"{}"作 ...

  8. python进阶学习笔记(二)

    1.模块和包的概念 python的解决方案是把同名的模块放到不同的包中 1.1,导入模块 要使用一个模块,我们必须首先导入该模块.Python使用import语句导入一个模块.例如,导入系统自带的模块 ...

  9. JDBC 基础

    JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口 ...

  10. Sublime Text编辑远程Linux服务器上的文件

    sublime有个叫sftp的插件,可以通过它直接打开远程机器上的文件进行编辑,并在保存后直接同步到远程linux服务器上. 用Package Control安装插件 按下Ctrl+Shift+P调出 ...