0

我正在尝试实现一个通用的 http 处理程序错误,但我发现了一个错误的行为。我的错误组件仅在第二次单击后才更新消息错误,但我不知道为什么。

代码在 StackBlitz 中可用:在此处输入链接描述

在 app.component.ts 点击我尝试一个 http 请求,它会失败,只是为了抛出一个错误。

 onClick() {
    this.http
      .get('http://localhost:8080/test')
      .pipe(catchError(this.errorHandler))
      .subscribe(() => {});
  }

  errorHandler(error: HttpErrorResponse) {
    return throwError(error.message);
  }

所有错误都在 global.error.ts 中处理,每个错误都添加到 error.service.ts 中:

export class GlobalErrorHandler implements ErrorHandler {
  constructor(private errorService: ErrorService) {}

  handleError(error: Error) {
    this.errorService.add('New Error');
  }
}

error.service.ts 使用 BehaviorSubject 并通知我的 error.component.ts:

export class ErrorService {
  public notification = new BehaviorSubject<string>('Initial Value');

  add(err: string) {
    this.notification.next(err);
  }
}

最后,error.component.ts 必须在屏幕上更新消息错误,但它只在第二次单击时有效,但 console.log 完美运行。

export class ErrorComponent implements OnInit {
  public errorMessage: string = '';

  constructor(public errorService: ErrorService) {}

  ngOnInit() {
    this.errorService.notification.subscribe({
      next: (notification) => {
        console.log('Error Component');
        this.errorMessage = notification;
      },
    });
  }
}

问题:

  1. 这种行为有什么原因吗?
  2. 对实现全局处理程序 Http 错误有什么建议吗?
4

1 回答 1

1

您只需要使用强制更改检测ChangeDetectorRef

  constructor(
    public errorService: ErrorService,
    private cd: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.errorService.notification.subscribe({
      next: (notification) => {
        console.log('Error Component');
        this.errorMessage = notification;
        this.cd.detectChanges();
      },
    });
  }

https://stackblitz.com/edit/angular-ivy-tzt7xk?file=src/app/error/error.component.ts

或者,包装.next()调用NgZone.run()还可以让更改检测在其订阅中获取更改。

  constructor(private ngZone: NgZone) {}

  public notification = new BehaviorSubject<string>('Initial Value');

  add(err: string) {
    this.ngZone.run(() => {
      this.notification.next(err);
    });
  }

我建议也直接用async管道显示主题。

{{ errorService.notification | async }}

https://stackblitz.com/edit/angular-ivy-wknur7?file=src/app/error.service.ts

此处的更多信息:更改 subscribe 中的变量后,Angular 6 View 不会更新

总之,Angular 仅在变量在“Angular Zone”内更改时才更新视图。第二次按下按钮时,它只是拾取第一个值,而不是第二个值。

于 2022-03-01T01:17:04.417 回答