如何使用ngrx/effects执行多个相关的操作/效果/操作

cma*_*son 34 ngrx

我正在使用ngrx/store 1.5以及thunk中间件的应用程序,我正在尝试移动到ngrx/store 2.0和ngrx/effects.关于如何处理多个相关的动作和/或效果,我有几个问题.

我意识到thunks vs effect的"心态"是不同的,我试图了解差异.我已经查看了可用的示例应用程序,并且没有找到任何看起来适合我正在尝试的内容,所以也许我仍然接近它完全错误.

场景1

以下是处理向服务器发出登录请求的副作用:

@Effect login$: any = this.updates$
    .whenAction(LoginActions.LOGIN)
    .map(toPayload)
    .switchMap(payload => 
        this.loginService.login(payload.user, payload.password)
            .map(result => this.actions.loginSuccess(value))
            .catch((error) => Observable.of(this.loginError(error)))
));
Run Code Online (Sandbox Code Playgroud)

鉴于最初的副作用,成功登录时触发导航到"主页"屏幕的"正确"或"建议"方式是什么?这也可以概括为简单地触发一系列动作或操作.

我考虑过几个选项:

(a)登录成功触发的另一个效果,即触发后续动作以触发导航?

@Effect navigateHome$: any = this.updates$
    .whenAction(LoginActions.LOGIN_SUCCEEDED)
    .mapTo(this.actions.navigateHome());
Run Code Online (Sandbox Code Playgroud)

(b)登录成功触发的另一个效果,即执行导航操作?

@Effect navigateHome$: any = this.updates$
    .whenAction(LoginActions.LOGIN_SUCCEEDED)
    .do(this.navigateHome())
    .filter(() => false);
Run Code Online (Sandbox Code Playgroud)

(c)将额外行动与初始登录效果所发出的行动联系起来?(样本显然不太正确,但给出了想法)

@Effect login$: any = this.updates$
    .whenAction(LoginActions.LOGIN)
    .map(toPayload)
    .switchMap(password => Observable.concat(
        this.loginService.login(passcode)
            .map(result => this.actions.loginSuccess(value))
            .catch((error) => Observable.of(this.loginError(error))),
        Observable.of(this.actions.navigateHome())
    ));
Run Code Online (Sandbox Code Playgroud)

(d)其他?

情景2

考虑需要按顺序进行多个请求的情况,并且随着每个请求开始,我们想要更新"状态"以便可以向用户提供反馈.

这些行中某事的thunk示例:

multiphaseAction() {
    return (dispatch) => {
        dispatch(this.actions.updateStatus('Executing phase 1');
        this.request1()
            .flatMap(result => {
                dispatch(this.actions.updateStatus('Executing phase 2');
                return this.request2();
            })
            .flatMap(result => {
                dispatch(this.actions.updateStatus('Executing phase 3');
                return this.request3();
            })
            ...
    }
}
Run Code Online (Sandbox Code Playgroud)

再次,使用效果方法的"正确"或"建议"方式是什么?

这个我更加坚持,不知道除了添加某些东西之外还能做些什么.do(this.store.dispatch(this.actions.updateStatus(...))......

Leo*_*ley 17

导航场景的答案是你的回答

@Effect navigateHome$: any = this.updates$
    .whenAction(LoginActions.LOGIN_SUCCEEDED)
    .do(this.router.navigate('/home'))
    .ignoreElements();
Run Code Online (Sandbox Code Playgroud)

说明:您对LOGIN_SUCCESS做出反应,并且因为路由器没有返回新操作,我们需要停止流的传播,我们通过过滤所有内容来完成.

如果您忘记过滤,路由器将返回undefined,这反过来将导致reducer减少未定义的值,这通常会在尝试读取type操作时导致空指针

另一种解决方法是使用https://github.com/ngrx/router-store

查看有关如何将路由器存储添加到您的应用程序的文档.

同样的效果现在看起来像这样.

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

@Effect navigateHome$: any = this.updates$
    .whenAction(LoginActions.LOGIN_SUCCEEDED)
    .map(() => go(['/home']));
Run Code Online (Sandbox Code Playgroud)

go操作将调度路由器减速器将拾取的路由器操作并触发路由更改.