如何调度一个空动作?

Posted

技术标签:

【中文标题】如何调度一个空动作?【英文标题】:How to dispatch an empty action? 【发布时间】:2017-02-07 06:42:00 【问题描述】:

我正在使用ngrx/effects。

如何分派一个空操作?

这就是我现在的做法:

 @Effect() foo$ = this.actions$
    .ofType(Actions.FOO)
    .withLatestFrom(this.store, (action, state) => ( action, state ))
    .map(( action, state ) => 
      if (state.foo.isCool) 
        return  type: Actions.BAR ;
       else 
        return  type: 'NOT_EXIST' ;
      
    );

因为我必须返回一个动作,所以我使用return type: 'NOT_EXIST' ;

有没有更好的方法来做到这一点?

【问题讨论】:

【参考方案1】:

我使用过类似的未知操作,但通常是在 reducer 单元测试的上下文中。

如果您对在效果中做同样的事情感到不安,您可以使用mergeMapObservable.of()Observable.empty() 来有条件地发出动作:

@Effect() foo$ = this.actions$
  .ofType(ChatActions.FOO)
  .withLatestFrom(this.store, (action, state) => ( action, state ))
  .mergeMap(( action, state ) => 
    if (state.foo.isCool) 
      return Observable.of( type: Actions.BAR );
     else 
      return Observable.empty();
    
  );

【讨论】:

【参考方案2】:

我会这样做:

@Effect() foo$ = this.actions$
    .ofType(Actions.FOO)
    .withLatestFrom(this.store, (action, state) => ( action, state ))
    .filter(( action, state ) => state.foo.isCool)
    .map(( action, state ) => 
      return  type: Actions.BAR ;
    );

【讨论】:

【参考方案3】:

我正在寻找的解决方案涉及使用@Effect( dispatch: false )

  @Effect( dispatch: false )
  logThisEffect$: Observable<void> = this.actions$
    .ofType(dataActions.LOG_THIS_EFFECT)
    .pipe(map(() => console.log('logThisEffect$ called')));

【讨论】:

这是错误的,在他的代码中他有时想发送一个动作,有时什么也不发送。【参考方案4】:

选择的答案不再适用于 rxjs6。所以这是另一种方法。

虽然我更喜欢在另一个答案中描述的大多数情况下进行过滤,但使用 flatMap 有时会很方便,尤其是当您处理复杂的事情时,对于过滤功能来说太复杂了:

import  Injectable  from '@angular/core';
import  Actions, Effect, ofType  from '@ngrx/effects';
import  flatMap  from 'rxjs/operators';
import  EMPTY, of  from 'rxjs';

@Injectable()
export class SomeEffects 
  @Effect()
  someEffect$ = this._actions$.pipe(
    ofType(SomeActionTypes.Action),
    flatMap((action) => 
      if (action.payload.isNotFunny) 
        return of(new CryInMySleepAction());
       else 
        return EMPTY;
      
    ),
  );

  constructor(
    private _actions$: Actions,
  ) 
  

【讨论】:

【参考方案5】:

从 ngrx 8 开始,如果您尝试调度一个空操作,您将收到一个运行时错误,所以我认为只需将它们过滤掉,这样它们就不会被调度。

@Effect() foo$ = this.actions$.pipe(
    ofType(Actions.FOO),
    withLatestFrom(this.store, (action, state) => ( action, state )),
    map(( action, state ) => 
      if (state.foo.isCool) 
        return  type: Actions.BAR ;
      
    ),
    filter(action => !!action)
);

【讨论】:

在 RxJs ~6.6.3 中像魅力一样工作,谢谢!【参考方案6】:

如果您不想调度操作,则只需将 dispatch 设置为 false:

 @Effect()
  foo$ = createEffect(() =>
    this.actions$.pipe(
      ofType(Actions.FOO),
      map(t => [])
    ),
     dispatch: false 
  );

【讨论】:

【参考方案7】:

对于"rxjs": "~6.6.6",平面地图已被合并地图所破坏,我们可以使用相同的行为

import  map, switchMap, catchError, mergeMap  from 'rxjs/operators';
import  of, EMPTY  from 'rxjs';

    addCategorie$ = createEffect(() =>
        this.actions$.pipe(
          ofType(ADD_CATEGORY),
          mergeMap((category) => this.categoryService.post(category.isCategoryOrVendor, category.model)
            .pipe(
              mergeMap(() => 
                this.backService.back();
                return EMPTY;
              ),
              catchError((error) => of(CATEGORY_ERROR(error)))
            )
          )
        )
      );

【讨论】:

以上是关于如何调度一个空动作?的主要内容,如果未能解决你的问题,请参考以下文章

NGXS:如何测试一个动作是不是被调度?

如何一个接一个地调度两个异步 redux 动作?

如何从 getInitialProps 内部调度一个动作?

如果 thunk 动作创建者中的 thunk 动作已被调度,我如何检查一个笑话测试?

如何在同一个史诗中调度多个动作

如何同时调度多个 ngrx 动作