web-dev-qa-db-ja.com

Angular NgRxエフェクト内のルーターナビゲーション

Angularルーターには、NgRxエフェクト内で使用する制限がありますか?

NgRxの学習を開始したばかりで、次のコードがあります。

@Effect() public authenticate$ = this.actions$
    .ofType(authenticationActions.AUTHENTICATE)
        .switchMap((action: AuthenticateAction) => this.authenticationService.authenticate(action.payload)
            .map((data: TokenData) => {
                const user: User = {
                    token: data.token,
                    username: 'dummy',
                };
                console.log(data);
                this.router.navigateByUrl('/');
                return new authenticationActions.AuthenticateSuccessAction(user);
            })
            .catch(error => { console.log(error); return Observable.throw(error); })
        );

コンソールはデータ変数をログに記録し、AuthenticateSuccessActionアクションがトリガーされているため、ルーター行は実行されていますが、ナビゲーションは行われていません。

9
RBasniak
@Effect() public authenticate$ = this.actions$.pipe(
    ofType(authenticationActions.AUTHENTICATE),
     map(action => action.payload),
    exhaustMap((auth: any) => 
      this.authenticationService.authenticate(auth)
        .map((data: TokenData) => {
            return user: User = {
                token: data.token,
                username: 'dummy',
            };
        }).catch(error => { console.log(error); return Observable.throw(error); 
       }).pipe(
          map(user =>new authenticationActions.AuthenticateSuccessAction(user))
        )
    );)

  @Effect({ dispatch: false })
   loginSuccess$ = this.actions$.pipe(
     ofType(authenticationActions.AuthenticateSuccessAction),
     tap(() => this.router.navigate(['/']))
   );

ExhaustMapを使用し、「AuthenticateSuccessAction」アクションをディスパッチするときに、リダイレクトのために別の効果を実行します。

個人的には、すべてのサービスをエフェクトから切り離したいのですが、ログイン成功後にcatchError()演算子を使用して、ログインに失敗した場合に別のアクションをディスパッチできます。

これがうまくいくことを願っています。 PS:私はこの答えを確認しませんでしたが、ロジックはこのようなものです。

16
m.akbari

リダイレクトのような別の効果を作成しないようにするアプローチが必要です。

this.actions$.pipe(
  ofType(authenticationActions.AUTHENTICATE),
  switchMap(action =>
    this.authenticationService.authenticate(action.payload).pipe(
      map(data => new authenticationActions.successAction(data)),
      tap(() => this.router.navigate(['/'])),
      catchError(error => new authenticationActions.failAction(error))
    )
);

問題は、サービス呼び出しが失敗した場合、tapが呼び出されないことです。失敗した場合、maptapの両方がスキップされ、catchErrorが優先されます。 。

1
dhilt