简体   繁体   English

Angular,RxJS主题问题

[英]Angular, RxJS Subject Issues

I am building a custom error handler for my Angular application that handles the error and then adds an error to a list to show to the user. 我正在为Angular应用程序构建一个自定义错误处理程序,该处理程序处理错误,然后将错误添加到要显示给用户的列表中。 The error handler works as expected; 错误处理程序按预期工作; it catches the error, uses the Angular Injector , gets an instance of the service needed to add the error to a list, and adds it to the list. 它捕获错误,使用Angular Injector ,获取将错误添加到列表所需的服务的实例,并将其添加到列表。 That service should then use the Rxjs Subject.next() function to send that list to all who have subscribed to the list. 然后,该服务应使用Rxjs Subject.next()函数将该列表发送给所有已订阅该列表的人。 This is where the weirdness happens. 这就是怪异发生的地方。

For background information, I have a button set up that makes an HTTP call to an invalid URL, just so an error is created on demand and can be caught by the application. 对于背景信息,我设置了一个按钮,可以对无效的URL进行HTTP调用,只是这样可以根据需要创建错误并可以由应用程序捕获。

The first time you click the button, an error comes in, it is caught and sent to the service, but it doesn't show on the page (looping over that list to output them in a component). 首次单击该按钮时,会出现错误,该错误会被捕获并发送到服务,但不会在页面上显示(循环显示该列表以将其输出到组件中)。 The second time you click the button, an error does show on the screen. 第二次单击该按钮时,屏幕上确实显示错误。 Same with the third and fourth, but there is always one less alert on the screen than in the array. 与第三和第四相同,但屏幕上的警报总是比阵列中少。

Then, when you remove an alert from the array the first time, it is definitely removed but you can't tell because that extra alert finally shows. 然后,当您第一次从阵列中删除警报时,肯定会删除该警报,但您无法分辨,因为最终会显示该警报。 Subsequent clicks remove the other alerts. 随后的点击将删除其他警报。

Now let's go back to adding alerts to the array. 现在,让我们回到将警报添加到阵列中。 The first time you click the button, nothing happens on the screen, but if you console.log the array you can see that it has added an item to the array. 第一次单击该按钮时,屏幕上没有任何反应,但是如果您console.log阵列,则可以看到它已向阵列添加了一项。 Click it again and an alert shows on the screen. 再次单击它,屏幕上将显示警报。

So it seems like each click is actually emitting, or passing, the array one time behind what you expect, if that makes sense. 因此,似乎每次点击实际上是在发射或传递数组,比您期望的晚了一次,如果这是有道理的。 I'm not sure why this is happening. 我不确定为什么会这样。 This should be pretty straight forward. 这应该很简单。 Any help would be greatly appreciated. 任何帮助将不胜感激。

You can see the working example on StackBlitz here . 您可以在此处查看StackBlitz上的工作示例。

After many trying i have figure why your actual code is not working. 经过多次尝试,我想出了为什么您的实际代码无法正常工作。 Is because your ErrorHandler catch all Exception inside Angular. 是因为您的ErrorHandler在Angular中捕获了所有Exception。 and you keep remind instead of let angular propagate this exception where she have to be manage. 而且您会不断提醒自己,而不是让Angular在必须管理的地方传播此异常。

Example of what i try to explain 我试图解释的例子

So i have replace your ErrorHandler by HttpInterceptor : 所以我已经用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);
      }));
  }
}

And add reference on my app.module : 并在我的app.module上添加引用:

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

Online sample 在线样本

Not relevant to your question but you can also check how i have change app-alert-toaster to manage onPush strategy and only Observable async pipe inside html side. 与您的问题无关,但是您也可以检查我如何更改app-alert-toaster来管理onPush策略以及html侧内仅可观察到的异步管道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM