在ngrx / effect中分派多个动作的最佳方法是什么?

时间:2018-05-31 16:58:54

标签: javascript angular typescript ngrx ngrx-store

我正在使用Angular 6,ngrx / store。我有这样的效果,负责更新事物。取决于一些逻辑,我想派遣不同的行动。可以这样做吗?如果我使用map @Effect() dispathMultipleActions$ = this.actions$.pipe( ofType(ActionTypes.UpdateSomething), map(() => { const actions: Action[] = []; const array = [1, 2, 3, 4, 5]; array.forEach(item => { if (item > 3) { actions.push(new DeleteAction(item)); } else { actions.push(new ChangeAction(item)); } }); return actions; }) ); 的内容,有什么区别?有没有更好的方法来解决这个问题?

SignupForm

3 个答案:

答案 0 :(得分:9)

效果会转换动作流,因此您可以将动作流作为输入和输出。在您的示例中,您将操作映射到操作数组。动作数组流不是有效的输出类型。您需要展平该数组,这意味着您不会将数组本身发送到输出流中,而是将其每个元素都发送出去。

而不是:

max

你应该这样做:

import json
lookup = ["CARDINALS", "BUFFALO", "DOLPHINS", "COWBOYS"]
url = 'api url'
data = requests.get(url)
team_data = json.loads(data.content)
new_teams = [i for i in team_data if i['team_id'] in lookup]
min_win = min(new_teams, key=lambda x:x['wins'])['wins']
max_win = max(new_teams, key=lambda x:x['wins'])['wins']
change_win = (max_win-min_win)/float(min_win+max_win)

要将Observable of数组展平为每个元素的Observable,您可以使用其中一个运算符input: --a-------a------> output: --[b,c]---[b,c]--> input: --a-------a------> output: --b-c-----b-c--> mergeMap。在大多数情况下,switchMap将是正确的选择。如果您想了解有关这些运算符的更多信息,请查看此answer

exhaustMap

答案 1 :(得分:1)

我遇到过同样的情况(假设 NgRx 10 或更高版本),我有不同的观点,更基本的使用效果的方法。在一个地方依次触发多个动作,特别是在单个效果中,是反模式。 从本质上讲,保持动作和潜力减少的一致general flow of application state in NgRx 很重要。正如 NgRx 架构所预见的那样。

遵循 the 3 effect rules 已经有助于避免困难情况:

  1. 将效果命名为效果的名称
  2. 让你的效果只做一件事
  3. 只发出一个动作

这样,它可以帮助您遵循 separation of concerns 设计模式,这当然也可以帮助您将 NgRx 效果变得更易于单元测试。

回到您的示例,您可以通过中间代理操作简单地分离您想要执行的操作(2 个附加操作)。

在您的情况下,除非出现特殊逻辑,否则您可能甚至不需要原始效果 dispathMultipleActions$。 (也许,它可能属于一个更易于单元测试的状态 Reducer)。

假设 ActionTypes.UpdateSomething 已经有一个数组有效负载对象,您可以将 dispathMultipleActions$ 拆分为单个对象,因此您可以执行以下操作:

@Effect()
deleteAction$ = this.actions$.pipe(
    ofType(ActionTypes.UpdateSomething),
    concatMap(from(new Promise((array) => {
        array.forEach(item => {
            if (item > 3) {
                //do something
            }
        });
    }))),
    {dispatch: false}
);

@Effect()
changeAction$ = this.actions$.pipe(
    ofType(ActionTypes.UpdateSomething),
    concatMap(from(new Promise((array) => {
        array.forEach(item => {
            if (item <= 3) {
                //do something
            }
        });
    }))),
    {dispatch: false}
);

答案 2 :(得分:0)

我在Ngrx 10中遇到了同样的问题,返回数组的解决方案似乎不再起作用...

我的解决方案是使用this.store$.dispatch( myAction(...) )

`

mergeMap((action: RegisterRequest) => {
  // check for register request success

  // for all actions from 0 to (last -1), use a dispatch() :
  this.store$.dispatch( RegisterSuccess() );

  // and the last action is returned:
  return LoginRequest(action.payload);

})