在效果失败/错误的情况下防止路由器导航

时间:2017-02-12 15:38:06

标签: redux rxjs rxjs5 ngrx ngrx-effects

我正在迁移以使用 ngrx效果而且我遇到以下问题:因为dispatch返回void我不确定如果我的错误发生,如何阻止路由器导航ngrx效应(例如来自this.userAccountService.updateFirstName(...)。

来自我的组件类:

  updateFirstName() {
    this.formStatus.submitted = true;
    if (this.formStatus.form.valid) {
      //Dispatch from the store
      this.store.dispatch(new UpdateFirstNameAction(this.formStatus.form.value.firstName));
      //Undesired behavior: will navigate even in case of error/failure!
      this.router.navigate(['/dashboard/useraccount']);
    }
  }

从我的效果课:

  @Effect()
  updateFirstName$: Observable<Action> = this.actions$
    .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME)
    .map((action: UpdateFirstNameAction) => action.payload)
    .switchMap(firstName =>
      this.userAccountService
        .updateFirstName(firstName)
        .map(() => new UpdateFirstNameSuccessAction(firstName))
        //I obviously can't navigate from here
    );

我不确定使用路由器以便从效果中导航是一种很好的做法(甚至可能)。

有人可以建议一个干净的解决方案,以防止路由器导航,以防我的效果发生错误吗?

2 个答案:

答案 0 :(得分:1)

我建议使用@ngrx/router-store模块。有了它,您可以创建路由操作,并使用它,您有几个选项。

您可以从单个效果中发出多个动作。因此,您的效果可以使用const发出两个操作:您的成功操作和路由操作(使用go操作创建者创建):

concatMap

但是,您可能还需要考虑使用仅管理路由的单独效果:

import { go } from '@ngrx/router-store';
import 'rxjs/add/operator/concatMap';

@Effect()
updateFirstName$: Observable<Action> = this.actions$
  .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME)
  .map((action: UpdateFirstNameAction) => action.payload)
  .switchMap(firstName => this.userAccountService
    .updateFirstName(firstName)
    .concatMap(() => [
      new UpdateFirstNameSuccessAction(firstName),
      go(['/dashboard/useraccount'])
    ])
  );

要考虑的另一件事是单个效果可以响应多个动作,因此您可以使用简单动作类型到路由映射的表来执行以下操作:

import { go } from '@ngrx/router-store';
import 'rxjs/add/operator/mapTo';

@Effect()
updateFirstRouting$: Observable<Action> = this.actions$
  .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS)
  .mapTo(go(['/dashboard/useraccount']);

无论您选择哪个选项,使用在效果中启动的导航的路由操作都可以使事情更容易测试。编写效果测试很容易,以确保当效果收到特定操作时,它会发出适当的操作。有关测试效果的更多信息here

答案 1 :(得分:0)

你可以采用以下两种方式之一。

  1. 使用效果,捕捉SUCCESS操作,然后重定向:

    @Effect() someeffect$: Observable<Action> = this.actions$
        .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS)                
        .do(action => /* do redirect (action.payload) */);
    
  2. 订阅:

    让我们说这是你的状态:

    {
        account: {
            username: null
        }
    }
    

    组件:

    var username$ = this.store.select(account => account.username);
    
    username$.subscribe(user => {
        // the user have changed due to reducer who is getting the action with new user.
        // do here redirect...
    });