如何正确捕获 @ngrx/effects 错误?

huangapple go评论86阅读模式
英文:

How to catch @ngrx/effects errors properly?

问题

我知道这个问题已经被问过很多次,但请记住我的特定问题,因为我找不到能够正确解决它的方法。

我有一个 effect,它应该按特定顺序执行多个 HTTP 请求 - 调用 1、调用 2、调用 3。我希望能够捕获任何错误,无论在整个链中的哪个地方抛出。我希望保持 rxjs 操作符的结构尽可能扁平,以避免嵌套的混乱代码。

以下是示例代码:

getMockDataEffect$ = createEffect(
    () => this.actions$.pipe(
      ofType(ApiGetMockData),
      concatMap(() => {
        return this.mockApi.mock1().pipe(
          concatMap(() => {
            return this.mockApi.mock2();
          }),
          concatMap(() => {
            return this.mockApi.mock3();
          }),
          map(res => ApiSuccess({ data: res })),
          catchError(error => of(ApiError({ error }))),
        )
      }
      )
    )
  )

在上面的示例中,如果在 mock2mock3 中发生错误,它将被成功捕获。然而,如果在 mock1 中发生错误,错误将完全不会被捕获。

我的问题是:我应该如何构建我的 effect,以使我的 catchError 操作符可以捕获发生在 mock1mock2mock3 中的任何错误,而不会完成 effect 的可观察对象?也就是说,如果发生错误,我应该能够分派动作并在之后成功运行 effect。

这里有一个StackBlitz演示

英文:

I know this question has been asked several times, but keep in mind my specific issue, because I couldn't find anything that solves it properly.

I have an effect that should perform multiple HTTP requests in a specific order - call 1, call 2, call 3. I want to be able to catch any error that is being thrown throughout the chain. I want to keep the structure of the rxjs operators as flat as possible to avoid nested spaghetti code.

Here's sample code:

getMockDataEffect$ = createEffect(
    () => this.actions$.pipe(
      ofType(ApiGetMockData),
      concatMap(() => {
        return this.mockApi.mock1().pipe(
          concatMap(() => {
            return this.mockApi.mock2();
          }),
          concatMap(() => {
            return this.mockApi.mock3();
          }),
          map(res => ApiSuccess({ data: res })),
          catchError(error => of(ApiError({ error }))),
        )
      }
      )
    )
  )

In the example given above, if an error occurs in mock2 or mock3, it would be successfully caught. However, if one occurs in mock1, the error won't be caught at all.

My question is: how do I structure my effect in such a way that my catchError operator would catch any error occurring in mock1, mock2 or mock3, without completing the effect's observable? Meaning, if an error occurs, I should be able to dispatch the action and run the effect successfully after that.

Here's a StackBlitz demo.

答案1

得分: 2

我认为你的示例很好。

问题在于 throw,因为我认为这是用于JavaScript执行的,它只会停止因为没有被捕获。

一个现实的情况是函数以Observable格式返回错误,为此你必须使用 throwError。当HTTP请求失败时,它将成为一个错误的Observable。

所以要使你的情况工作,将 mockapi.service.ts 更改为以下内容:

import { Injectable } from '@angular/core';
import { of, throwError } from 'rxjs';
import { map, tap } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class MockApiService {

  mock1() {
    //return throwError('e1');
    return of('mock1');
  }

  mock2() {
    // return throwError('e2');
    return of('mock2');
  }

  mock3() {
    // return throwError('e3');
    return of('mock3');
  }
}

取消注释任何函数上的 throwError 来模拟它已经出现了错误。

英文:

I think your example is good.

The issue is the throw because I think this is for JavaScript execution and it just stops because it is not being caught.

A realistic scenario would be that the functions return an error in an Observable format and for this you have to use throwError. When an http request fails, it will be an error observable.

So to get your situation working, change mockapi.service.ts to the following:

import { Injectable } from '@angular/core';
import { of, throwError } from 'rxjs';
import { map, tap } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class MockApiService {

  mock1() {
    //return throwError('e1');
    return of('mock1');
  }

  mock2() {
    // return throwError('e2');
    return of('mock2');
  }

  mock3() {
    // return throwError('e3');
    return of('mock3');
  }
}

Uncomment any of the throwErrors on whatever function to simulate it has errored.

huangapple
  • 本文由 发表于 2020年1月3日 19:52:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/59578148.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定