Angular2 @ngrx/store / effects - 在哪里调用服务函数

Angular2 @ngrx/store / effects - where to call service functions

我正在使用@ngrx/store 和@ngrx/effects 制作一个Angular 2 应用程序。

我正在努力理解将逻辑放在 actions/effects 等之外的位置以及在哪里调用服务功能。

例如,使用身份验证...

  1. 当用户单击 登录 时,这将调度一个 AUTH_REQUEST 操作,并将登录凭据作为有效负载。
  2. 效果查找此操作并调用 API。
  3. 成功的结果调用 AUTH_SUCCESS 操作,将响应对象中的令牌、用户名等作为有效载荷,传递给 reducer 以更新 AuthState

例如:在AuthEffects

@Effect() authenticate$ = this.updates$
.whenAction(AuthActions.AUTHENTICATE_REQUEST)
.switchMap(update => this.api.post('/authenticate', update.action.payload)
  .map((res:any) => ({type: AuthActions.AUTHENTICATE_SUCCESS, payload: res.json()}))
  .catch((err:any) => Observable.of({ type: AuthActions.AUTHENTICATE_ERROR, payload: err }))
);

AuthReducer

 case AuthActions.AUTHENTICATE_SUCCESS:
  return Object.assign({}, state, <AuthState>{
    processing: false,
    failed: false,
    isLoggedIn: true,
    token: action.payload.token,
    username: action.payload.username,
    accountId: action.payload.accountId,
  });

我想知道的是:

  1. 在处理完 AUTH_SUCCESS 操作后,在哪里调用路由器来更改页面。我是从效果反应链中执行此操作还是...??
  2. 我有一个 AuthService 需要在 LocalStorage 中存储凭据(令牌等)。我应该在哪里调用这个 "store the token" 即 authService.store(userCredentials)

感谢任何帮助。

显然,这不是确定的答案;这正是我选择要做的。

CodeSequence/ngrx-‌​store-router 实现 v3 路由器的操作。但是,它没有实现动作创建器——只有 string 类型。我使用了一个简单的动作创建器,这样我就不必到处都有动作文字了:

import * as ngrxStoreRouter from "ngrx-store-router";

@Injectable()
export class RouterActions {

    static NAVIGATE: string = ngrxStoreRouter.RouterActions.navigating;
    navigate(url: string): Action {

        return {
            payload: { url },
            type: RouterActions.NAVIGATE
        };
    }
}

并且我使用效果 class 来调度路由器操作:

@Injectable()
export class RouterEffects {

    ...

    @Effect()
    createUser(): Observable<Action> {

        return this.stateUpdates_
            .whenAction(AuthActions.CREATE_USER_SUCCESS)
            .map((update) => update.action.payload)
            .switchMap((payload) => {

                return Observable.of(this.routerActions_.navigate("/on-board"));
            });
    }

    ...
}

我的理由是这不涉及对路由一无所知的身份验证效果,它使编写路由器效果测试变得容易,并且路由器操作非常适合 @ngrx/store-devtools

关于你的第二个问题,我倾向于将其连接到一个 ..._SUCCESS 动作效果。

我有兴趣了解替代方法。

还有一个 ngrx "official" 库处理这些类型的功能,@ngrx/router-store. Right now @ngrx/router is being deprecated in favour of @angular/router 3.0.0 (now in RC1), as indicated by their migration guide. As a consequence, router-store is undergoing changes as well, to migrate to angular router, and there's a pending PR 解决了这个问题。 当一切都希望安定下来时,router-store 提供了一个用于导航目的的动作创建器,非常方便 return 来自 effects:

// ...
import { Effect, toPayload, StateUpdates } from '@ngrx/effects';
import { go } from '@ngrx/router-store';

// ... in custom effects class

@Effect() loginSuccess$: Observable<Action> = this.updates$
  .whenAction(LoginActions.LOGIN_SUCCEEDED)
  .map<ActionPayloads.LoginSucceeded>(toPayload)
  .do(successPayload => {
    // grab auth information you need to store
    // and save them now, accessing your local storage service

    const { authInfo, rememberMe } = successPayload;

    this.authStorage.save(authInfo, rememberMe);
  })
  .map(_ => go(homeRoutePath));

现在看来这不起作用,但应该会在路由器存储更新后立即恢复。 HTH

我是这样做的:

import { go } from '@ngrx/router-store';
...

@Injectable()
export class AuthEffects {

  constructor(
    private actions$: Actions,
    private authService: AuthService
  ) { }

  @Effect() loginSuccess$: Observable<Action> = this.actions$
    .ofType(auth.ActionTypes.LOGIN_SUCCESS)
    .map((action) => action.payload as AuthUser)
    .do((user: AuthUser) => console.info('welcome ' + user.name))
    .map(() => go(['/welcome']));

}

根据需要在最后的行动之前打电话给其他人 actions/Effects。当然,这个例子使用 '@ngrx/router-store'.

从官方仓库中阅读精彩的 example-app 代码。