10

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

我正在努力理解将逻辑放在动作/效果等之外的位置以及调用服务功能的位置。

例如,通过身份验证...

  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 中。我应该在哪里调用它来“存储令牌”,即authService.store(userCredentials).

任何帮助表示赞赏。

4

3 回答 3

4

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

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
        };
    }
}

我使用了一个效果类来调度路由器动作:

@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效果中的动作联系起来。

我有兴趣了解替代方法。

于 2016-08-15T22:00:59.347 回答
0

还有一个ngrx“官方”库处理这些类型的功能,@ngrx/router-store。现在 @ngrx/router 被弃用,取而代之的是 @angular/router 3.0.0(现在在 RC1 中),正如他们的迁移指南所示。因此,路由器存储也正在发生变化,以迁移到角度路由器,并且有一个待定的 PR 正在解决这个问题。当一切都希望稳定下来时,router-store 提供了一个用于导航目的的动作创建器,非常方便地从效果中返回:

// ...
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));

现在看来这不起作用,但是一旦路由器商店更新,它应该会回来。高温高压

于 2016-08-26T09:48:38.460 回答
0

我是这样做的:

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']));

}

根据需要在最终操作之前调用其他操作/效果。当然,这个例子使用'@ngrx/router-store'.

从官方 repo 中阅读令人惊叹的示例应用程序代码。

于 2017-01-24T04:04:18.050 回答