如何调度一个空动作?
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 单元测试的上下文中。
如果您对在效果中做同样的事情感到不安,您可以使用mergeMap
、Observable.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)))
)
)
)
);
【讨论】:
以上是关于如何调度一个空动作?的主要内容,如果未能解决你的问题,请参考以下文章