【问题标题】:Angular, RxJS Subject IssuesAngular、RxJS 主题问题
【发布时间】:2018-06-14 00:48:58
【问题描述】:

我正在为我的 Angular 应用程序构建一个自定义错误处理程序来处理错误,然后将错误添加到列表中以显示给用户。错误处理程序按预期工作;它捕获错误,使用 Angular Injector,获取将错误添加到列表所需的服务实例,并将其添加到列表中。然后该服务应该使用 Rxjs Subject.next() 函数将该列表发送给所有订阅该列表的人。这就是奇怪发生的地方。

关于背景信息,我设置了一个对无效 URL 进行 HTTP 调用的按钮,以便按需创建错误并可以被应用程序捕获。

第一次单击按钮时,会出现错误,它会被捕获并发送到服务,但它不会显示在页面上(循环该列表以将它们输出到组件中)。第二次单击该按钮时,屏幕上会显示错误。与第三个和第四个相同,但屏幕上的警报总是比数组中少一个。

然后,当您第一次从数组中删除警报时,它肯定会被删除,但您无法判断,因为额外的警报最终会显示。后续点击会删除其他警报。

现在让我们回到向数组添加警报。第一次单击该按钮时,屏幕上没有任何反应,但如果您console.log 数组,您可以看到它已向数组中添加了一个项目。再次单击它,屏幕上会显示一条警报。

因此,如果有意义的话,似乎每次点击实际上都会发出或传递数组,比您预期的要晚一次。我不确定为什么会这样。这应该很简单。任何帮助将不胜感激。

您可以查看工作示例on StackBlitz here

【问题讨论】:

  • 演示我们抛出编译器错误Can't resolve all parameters for ErrorHandlerService:
  • @martin 你还在看这个吗?打开项目时,我没有看到任何编译器错误。
  • 一切都按预期工作。问题是没有任何东西触发更改检测。此时。

标签: angular rxjs


【解决方案1】:

经过多次尝试,我明白了为什么您的实际代码不起作用。是因为您的 ErrorHandler 捕获了 Angular 中的所有异常。并且您不断提醒,而不是让 Angular 将这个异常传播到她必须管理的地方。

Example of what i try to explain

所以我用HttpInterceptor 替换了你的ErrorHandler

import { Injectable, Injector } from '@angular/core';
import { HttpInterceptor,HttpHandler, HttpRequest, HttpEvent,HttpErrorResponse } from '@angular/common/http';
import { Observable,empty, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

import { AlertToasterService } from '../alert-toaster/alert-toaster.service';

@Injectable()
export class ErrorHandlerService implements HttpInterceptor {

  constructor(private alertToasterService: AlertToasterService) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    return next.handle(request)
      .pipe(catchError((err: HttpErrorResponse) => {
        let errorMessage= 'An unknown error occurred.';
        if (err.error instanceof Error) {
          // A client-side or network error occurred. Handle it accordingly.
           errorMessage = err.error.message;
        } else {
          // The backend returned an unsuccessful response code.
          // The response body may contain clues as to what went wrong,
          errorMessage = err.message;
        }

        this.alertToasterService.addAlertToList({
            level: 'danger',
            message: errorMessage,
            dismissible: true
          });

        return throwError(err);
      }));
  }
}

并在我的 app.module 上添加参考:

  { 
      provide: HTTP_INTERCEPTORS, 
      useClass: ErrorHandlerService, 
      multi: true 
  },

Online sample

与您的问题无关,但您也可以查看我如何更改 app-alert-toaster 来管理 onPush 策略以及仅在 html 端内的 Observable 异步管道。

【讨论】:

  • 是的,这很好用,但这不是我想做的。我想捕捉 Angular 中的所有错误;这就是我的目标。捕获任何错误并将其显示给成员。我不仅想捕捉和显示 HTTP 错误。
  • 我仍然无法理解为什么第一项没有更新.. 我尝试通过 BehaviorSubject 进行更改,因为我怀疑主题初始化存在问题.. 然后我也尝试将 ToasterService 移动到app.module (我怀疑延迟服务注入或类似的问题)...但是这里没有一条线索是相关的。
猜你喜欢
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 2021-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 2019-02-10
相关资源
最近更新 更多