ngrx 효과의 switchMap에서 오류를 throw하는 방법

Aug 19 2020

ngrx8, rxjs6 및 angular 9를 사용하고 있습니다.

로그인 후 다른 서비스에 전화해야합니다. 그 서비스가 오류를 던질 때 내 효과의 catchError 부분을 처리하고 싶습니다. 문제는 try catch에서 오류를 포착하고 로그를 보지만 catchError트리거되지 않는다는 것입니다.

단순화 된 코드

    login$ = createEffect(() => { return this.actions$.pipe(

            ofType(AuthActions.login),
            switchMap((action) =>
                this.userService.login(action.userName, action.password)
                    .pipe(
                        switchMap((token) => {
                            return throwError(new Error('hello'));
                        }),
                        map((token) => AuthActions.loginSuccess()),
                        catchError((error) => {
                            console.error('error', error); // I don't see this in console

                            return of(AppError({ error }));
                        })),
            ),
            catchError((error) => {
                console.error('error 2', error);

                return of(AppError({ error }));
            }),
        );
    });

내 실제 코드

    login$ = createEffect(() => { return this.actions$.pipe(

            ofType(AuthActions.login),
            switchMap((action) =>
                this.userService.login(action.userName, action.password)
                    .pipe(
                        switchMap(async (token) => {
                            try {
                                await this.matrixService.initClient(action.userName, action.password);

                                return of(token);
                            }
                            catch (error) {
                                console.log('catch error', error); // I see this in console

                                return throwError(error);
                            }
                        }),
                        map((token) => AuthActions.loginSuccess()),
                        catchError((error) => {
                            console.error('error', error); // I don't see this in console

                            return of(AppError({ error }));
                        })),
            ),
            catchError((error) => {
                console.error('error 2', error);

                return of(AppError({ error }));
            }),
        );
    });

콘솔 출력

답변

1 RafiHenig Aug 19 2020 at 04:23

오히려 사용하는 것보다 Async-Await기다릴 구문 Promise에 의해 반환 matrixService.initClient(때문에 현재 상황에서 작동하지 않을 것이다 전체에 switchMap운영자가 기다리고하지 async그것을가로 변환하는 것처럼, 그것을 기다리지 않고 그것을 반환 고려, 기능) Observable에 (감사 switchMap연산자 수락 Promise) 결과 this.userService.login로 기다리고 있습니다.

login$ = createEffect(() => this.actions$
  .pipe(
    ofType(AuthActions.login),
    switchMap(({ userName, password }) => this.userService.login(userName, password)
      .pipe(
        switchMap(() => this.matrixService.initClient(userName, password)),
        map((token) => AuthActions.loginSuccess()),
        catchError((error) => {
          console.error('error', error);
          return of(AppError({ error }));
        })
      )
    ),
    catchError((error) => {
      console.error('error 2', error);
      return of(AppError({ error }));
    })
  )
);
HamzaZaidi Aug 19 2020 at 22:01

댓글에 따라 이전 답변을 조금 수정하겠습니다.

login$ = createEffect(() => this.actions$
  .pipe(
    ofType(AuthActions.login),
    switchMap(({ userName, password }) => this.userService.login(userName, password)
      .pipe(
        map((token) => AuthActions.loginSuccess())
        tap(() => this.matrixService.initClient(userName, password)),
      )
    ),
    catchError((error) => {
      console.error('error 2', error);
      return of(AppError({ error }));
    })
  )
);

I switch the order, always firing AuthActions.loginSuccess() and then this.matrixService.initClient(userName, password).

catchError does not need to be called twice, any error generated from service call will be catch in the outermost catchError operator.