在计算信号(角度)中多次抛出异常

问题描述 投票:0回答:1

我在 Angular 应用程序中使用信号。

我正在使用这样的

computed
信号,我自愿抛出异常来测试在“计算”信号中抛出异常时会发生什么,我的真实代码要复杂得多。

  public test: Signal<string> = computed(() => {
    throw new Error(`Testing throwing exception`);
    return 'foo';
  });
  <p>{{ test() }}</p>

当我查看控制台时,我看到异常被多次抛出(至少 15 次) exception in console

我使用 bugsnag 来报告意外异常,并且向 bugsnag 报告了多次而不是一次。

我找到的一个解决方案是在我的计算函数中添加一个 try catch 并手动向 bugsnag 报告,如下所示:

  public test: Signal<string> = computed(() => {
    try {
      throw new Error(`Testing throwing exception`);
      return 'foo';
    } catch (error) {
      Bugsnag.notify(error as NotifiableError);
      return '';
    }
  });

但是有没有更好的方法来处理这个用例?我猜想在“计算信号”中处理异常是很常见的

angular typescript exception signals
1个回答
0
投票

当计算函数中发生错误时,错误(与正常使用中的值一样)会被记住。因此,下次读取计算信号时,如果依赖关系没有改变,则计算函数将不会重新执行,并且将再次抛出记忆错误。

您可以使用此示例检查此行为:

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <button type="button" (click)="handleClick()">
      Click me
    </button>
    {{vComputed()}}
  `,
})
export class App {
  handleClick() {
    console.log('clicked');
  }

  vComputed = computed(() => {
    console.log('execution of computed function');
    throw Error('error');
  });
}

消息

execution of computed function
仅打印一次(因为信号没有依赖性,因此计算函数永远不会重新执行),每次读取计算信号时都会抛出错误(每次单击按钮,因为它会触发更改检测并刷新视图。

因此,我看到了两种处理计算信号错误的选项:

  1. 捕获计算函数内部的错误(如您在示例中所做的那样)并返回后备计算值。
@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <button type="button" (click)="handleClick()">
      Click me
    </button>
    {{getValue()}}
  `,
})
export class App {

  ...

  vComputed = computed<number>(() => {
    console.log('execution of computed function');
    try {
      throw Error('error');
    } catch(e) {
      return 0;
    }
  });
  1. 在方法中读取计算值,而不是直接在模板中执行。
@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <button type="button" (click)="handleClick()">
      Click me
    </button>
    {{getValue()}}
  `,
})
export class App {

  ...

  getValue() {
    try {
      return vComputed();
    } catch (e) {
      return 0;
    }
  }

两种解决方案之间存在细微差别,在第二个解决方案中,catch 块将在每次渲染时重新执行(每次调用

getValue
函数时),而在第一个解决方案中,回退值会被记忆,因此catch 块仅执行一次。

© www.soinside.com 2019 - 2024. All rights reserved.