首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用ngrx/effects执行多个相关操作/效果/操作

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

Stack Overflow用户
提问于 2016-06-04 18:17:30
回答 4查看 13K关注 0票数 37

我正在开发一个应用程序,该应用程序使用ngrx/store 1.5和thunk中间件,并试图迁移到ngrx/store 2.0和ngrx/effects。关于如何处理多个相关的操作和/或效果,我有几个问题。

我意识到,“思维模式”对大块头和特效是不同的,我正试图使我的头脑在不同的地方。我已经查看了可用的示例应用程序,没有发现任何似乎适合我尝试的应用程序,所以也许我仍然完全错误地对待它。

场景1

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

代码语言:javascript
运行
复制
@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)))
));

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

我曾考虑过以下几种选择:

(a)登录成功引发的另一个影响,即触发导航的后续行动?

代码语言:javascript
运行
复制
@Effect navigateHome$: any = this.updates$
    .whenAction(LoginActions.LOGIN_SUCCEEDED)
    .mapTo(this.actions.navigateHome());

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

代码语言:javascript
运行
复制
@Effect navigateHome$: any = this.updates$
    .whenAction(LoginActions.LOGIN_SUCCEEDED)
    .do(this.navigateHome())
    .filter(() => false);

(c)将附加行动与初始登录效果所发出的行动相一致吗?(样本显然不完全正确,但给出了想法)

代码语言:javascript
运行
复制
@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())
    ));

(d)其他?

场景2

考虑这样一种情况,即需要按顺序发出多个请求,当每个请求开始时,我们希望更新“状态”,以便能够向用户提供反馈。

类似于类似的事物的一个例子:

代码语言:javascript
运行
复制
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();
            })
            ...
    }
}

同样,在使用效果方法时,“正确”或“建议”的方法是什么?

这个我更坚持,不确定除了添加一些.do(this.store.dispatch(this.actions.updateStatus(...))之外还能做些什么.

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-06-21 06:22:06

导航场景的答案是b答案。

代码语言:javascript
运行
复制
@Effect navigateHome$: any = this.updates$
    .whenAction(LoginActions.LOGIN_SUCCEEDED)
    .do(this.router.navigate('/home'))
    .ignoreElements();

说明:您对LOGIN_SUCCESS作出反应,并且由于路由器不返回新的操作,所以我们需要停止流的传播,我们通过过滤所有的东西来完成这一工作。

如果您忘记了过滤,路由器返回未定义的,这反过来将导致还原器减少一个未定义的值,这通常导致一个空指针当它试图读取操作的type时。

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

查看有关如何将路由器商店添加到应用程序的文档。

同样的效果现在看起来是这样的。

代码语言:javascript
运行
复制
import { go } from '@ngrx/router-store';

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

go操作将发送路由器操作,路由器还原器将获取该动作并触发路由更改。

票数 20
EN

Stack Overflow用户

发布于 2016-06-28 09:06:48

场景1

考虑一下navigateHome是否应该改变状态。此外,是否从其他地方分派此navigateHome操作来实现相同的任务。如果是这样的话,返回一个操作是可行的。因此,备选案文A。

在某些情况下,备选案文B可能更有意义。如果navigateHome只改变了路由,那么它可能是值得考虑的。

附带注意:您可以在这里使用ignoreElements而不是filter(() => false)

场景2

我建议在这里将你的动作链接在多个效果中,并通过修改减速机中的每一个动作的状态给出反馈。

例如:

代码语言:javascript
运行
复制
@Effect() trigger$: Observable<Action> = this.updates$
    .whenAction(Actions.TRIGGER)
    .do(() => console.log("start doing something here"))
    .mapTo(Actions.PHASE1);

@Effect() phase1$: Observable<Action> = this.updates$
    .whenAction(Actions.PHASE1)
    .do(() => console.log("phase 1"))
    .mapTo(Actions.PHASE2);

@Effect() phase2$: Observable<Action> = this.updates$
    .whenAction(Actions.PHASE2)
    .do(() => console.log("phase 2"))
    .ignoreElements();

并通过修改状态给出反馈:

代码语言:javascript
运行
复制
function reducer(state = initialState, action: Action): SomeState {
    switch (action.type) {
        case Actions.TRIGGER: {
            return Object.assign({}, state, {
                triggered: true
            });
        }
        case Actions.PHASE1: {
            return Object.assign({}, state, {
                phase1: true
            });
        }
        case Actions.PHASE2: {
            return Object.assign({}, state, {
                phase1: false,
                phase2: true
            });
        }
        // ...
    }
}
票数 2
EN

Stack Overflow用户

发布于 2016-06-21 06:21:46

场景1

选项A和B都是好的选择,我认为,但也许选项A是有点太多,只是导航!如果您认为导航是这种副作用的一部分,也可以直接使用LoginActions.LOGIN中的路由器。

场景2

@Effects链接起来没有什么问题。分派一个动作(SET_1_REQUEST)来触发您的效果A。效果A返回一个操作(SET_1_SUCCESS),该动作由还原器拾取(现在您可以向用户显示该状态),它由效果B获取。

希望这是有意义的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37633564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档