【问题标题】:Angular 2 doesn't update view after exception is thrown抛出异常后Angular 2不更新视图
【发布时间】:2016-06-15 12:58:44
【问题描述】:

当 Angular 2 的异常处理程序捕获到异常时,UI 不再“更新”。

我有一个很简单的例子here:

import { Component, ExceptionHandler, Injectable, OnInit, provide } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';
import { Subject } from 'rxjs/Subject'

export interface Alert {
  message: string;
}

@Component({
  selector: 'my-app',
  template : `
  <h3>Parent</h3>
  {{aValue}}
  <br/>
  <br/>
  <button (click)='doIt()'>do it</button>
  <br/>
  <br/>
  <button (click)='breakIt()'>break it</button>
  `
})

export class App implements OnInit {
  private aValue: boolean = true
  constructor() { }
  
  alerts: Alert[] = [];
  
  doIt(){
    console.log('Doing It')
    this.aValue = !this.aValue
  }
  
  breakIt(){
    console.log('Breaking It')
    throw new Error('some error')
  }
}

bootstrap(App).catch(err => console.error(err));

Do It 按钮翻转boolean,这反映在模板中的插值中。但是,一旦按下Break It 按钮(这会引发错误),当按下“执行”按钮时,内插值不再更新。但是,控制台仍然会记录消息Doing it

我正在处理的问题是我想创建一个自定义异常处理程序来警告用户,并且可能会在出现问题时做一些工作来清除表单,但我看到的是如果我抛出一个单击按钮进行测试时出错,所有 UI 更新都会停止。但是,按钮继续起作用,这意味着如果表单处于良好状态,任何发布请求的按钮都会这样做。然而,UI 已停止更新并通知用户正在发生的事情。

我不确定这是区域问题还是其他问题,但尝试NgZone.run() 似乎并没有为我解决问题。如果错误是为了破坏组件的 UI,那么解决我的问题的正确方法是什么?

【问题讨论】:

  • 有趣。我看到的不同之处在于错误是由子组件引发的,并且他的 plunker 的视图继续更新。这是否意味着我只需要尝试...捕获父组件,所有子组件错误都不会导致视图中断?
  • 我认为做出一般性陈述并不容易。这总是取决于从哪里调用抛出的代码,以及如果调用了某些代码但没有以预期路径完成,是否会破坏任何东西。
  • 注明。不过,在我对这个假设的测试中,它似乎是正确的。我想我有一条前进的道路......可能是一个包装其他所有内容的父组件,并充当错误处理的最后一道防线。

标签: angular typescript exception


【解决方案1】:

自 Angular 4.1.1 (2017-05-04) https://github.com/angular/angular/commit/07cef36

fix(core):不要因为错误而停止变更检测

  • 防止出现错误时从区域退订
  • 防止在出错时取消订阅指令EventEmitters
  • 防止在开发模式下出现错误时分离视图
  • 确保 ngOnInit 仅被称为 1x(也在 prod 模式下)

它应该可以在没有额外代码的情况下工作

@Component({
  selector: 'my-app',
  template : `
    {{aValue}}
    <button (click)='doIt()'>do it</button>
    <button (click)='breakIt()'>break it</button>
  `
})

export class App implements OnInit {
  private aValue: boolean = true

  doIt(){
    console.log('Doing It')
    this.aValue = !this.aValue
  }

  breakIt(){
    console.log('Breaking It')
    throw new Error('some error')
  }
}

Plunker Example

【讨论】:

    【解决方案2】:

    在未处理的Exception 发生后,不要依赖代码执行。 您必须在预期发生的地方处理异常。

    错误处理: http://www.javascriptkit.com/javatutors/trycatch.shtml

    【讨论】:

    • 我正在尝试实现 Angular 2 的全局异常处理,希望不必在我的所有代码中添加 try...catch,但我描述的场景让我觉得我做不到t 采取这种方法。我确实看过 Günter 指出的问题,但现在我想知道我是否可以只在父组件上尝试捕获,因为该问题中的子组件不会破坏视图更新。我并不一定期望有什么问题发生,但是我的技术负责人坚持认为,无论我期望什么,错误捕获都会发生在任何地方。
    • 您不需要将所有内容都包装在 try/catch 中。例外是您在开发过程中的朋友。处理异常对于用户输入到您的应用程序中的任何内容都是有意义的,因为我们知道最终用户可以做一些疯狂的事情。异常可以帮助你发现你正在做的坏事。
    • 这就是我过去一直在做的事情,我同意例外是我的朋友。这里的问题是在生产中,我们希望将错误发布到服务器并通知用户发生了一些不好的事情。如果 Angular 不再更新它的视图,我就不能依赖 Angular 来做到这一点。我可能会在异常处理程序中回退到纯 javascript,但我也试图避免这种情况。
    猜你喜欢
    • 1970-01-01
    • 2016-08-23
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    相关资源
    最近更新 更多