Angular,RxJS主题问题

时间:2018-06-14 00:48:58

标签: angular rxjs

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

有关背景信息,我设置了一个按钮,可以对无效的URL进行HTTP调用,这样就可以根据需要创建错误,并且可以被应用程序捕获。

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

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

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

因此,如果有意义的话,似乎每次点击实际上都会排放或传递数组一次。我不确定为什么会这样。这应该是非常直接的。任何帮助将不胜感激。

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

1 个答案:

答案 0 :(得分:0)

经过多次尝试,我已经知道为什么你的实际代码不能正常工作。是因为你的ErrorHandler捕获了Angular中的所有异常。而且你要保持提醒,而不是让角度传播这个必须管理的例外。

Example of what i try to explain

所以我已将ErrorHandler替换为HttpInterceptor

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异步管道。