Angular,Http 错误阻止任何进一步的请求

Angular, Http Error blocks any further requests

服务器错误响应后,我的应用程序不再发送任何请求。

我正在发送请求:

getMachineRules(rules: Array<string>): Observable<RulesResults> {
    return this.http.post<RulesResults>('/rules', { nodes: rules })
      .pipe(
        catchError(this.handleError)
      );
  }

我的错误处理程序:

  handleError(error) {
    if (error.error instanceof ErrorEvent) {
      console.error('An error occurred:', error.error.message);
    } else {
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${JSON.stringify(error.error)}`);
    }
    return throwError('Something bad happened; please try again later.');
  }

我的管道是这样的:

  ngAfterViewInit() {
    this.rulesChanged
      .pipe(
        startWith({}),
        switchMap(() => {
          this.isLoadingResults = true;
          return this.settings.getMachineRules(this.currentRules);
        }),
        map(data => {
          this.isLoadingResults = false;
          this.resultsLength = data.inputs?.length || 0;
          return data;
        }),
        catchError(e => {
          console.log("Error caught");
          this.isLoadingResults = false;
          this.resultsLength = 0;
          return observableOf({ inputs: [] } as RulesResults);
        })
      ).subscribe(
        data => { return this.updateRules(data); },
      );
  }

我可以在控制台中看到“Error caught”消息,方法 updateRules() 似乎即使在错误情况下也能正常工作。

但是在 404 错误响应之后,ngAfterViewInit() 方法是 不再叫了。 UI 钢对相互作用产生反应。

一旦 Obsevable 失败,您将无法再次激活它,catchError 用于通过 returning 新的 observable[=27] 来处理错误=] 或抛出错误。 observableOf({ inputs: [] } as RulesResults) 用作 替代品 以防主流发生故障,这意味着您的主要 Observable 将 永远不会 再次发射。

考虑在您的管道末端使用 retry,或者有选择地使用您的 catchError return 源 Observable 本身,如下所示:

catchError((error, source) => {
 ....
  return source;
})

或者将 catchError 运算符放在 switchMap 中,这样只有内部流会失败,而外部(主要)流将保持活动状态,如下所示:

ngAfterViewInit() {
  this.rulesChanged
    .pipe(
      startWith({}),
      switchMap(() => {
        this.isLoadingResults = true;
        return this.settings.getMachineRules(this.currentRules).pipe(
          map(data => {
            this.isLoadingResults = false;
            this.resultsLength = data.inputs?.length || 0;
            return data;
          }),
          catchError(e => {
            console.log("Error caught");
            this.isLoadingResults = false;
            this.resultsLength = 0;
            return observableOf({ inputs: [] } as RulesResults);
          })
        )
      })
    ).subscribe(
      data => { return this.updateRules(data); },
    );