如何派发空动作?
How to dispatch an empty action?
我正在使用 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 一个动作,所以我使用 return { type: 'NOT_EXIST' };
。
有更好的方法吗?
我使用过类似的未知操作,但通常是在减速器单元测试的上下文中。
如果您对在效果中做同样的事情感到不安,您可以使用 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();
}
});
我会按以下方式进行:
@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 };
});
我正在寻找的解决方案涉及使用 @Effect({ dispatch: false })
。
@Effect({ dispatch: false })
logThisEffect$: Observable<void> = this.actions$
.ofType(dataActions.LOG_THIS_EFFECT)
.pipe(map(() => console.log('logThisEffect$ called')));
选择的答案不再适用于 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,
) {
}
}
从 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)
);
如果您不想派发一个动作,那么只需将 dispatch
设置为 false:
@Effect()
foo$ = createEffect(() =>
this.actions$.pipe(
ofType(Actions.FOO),
map(t => [])
),
{ dispatch: false }
);
在 "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)))
)
)
)
);
我正在使用 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 一个动作,所以我使用 return { type: 'NOT_EXIST' };
。
有更好的方法吗?
我使用过类似的未知操作,但通常是在减速器单元测试的上下文中。
如果您对在效果中做同样的事情感到不安,您可以使用 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();
}
});
我会按以下方式进行:
@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 };
});
我正在寻找的解决方案涉及使用 @Effect({ dispatch: false })
。
@Effect({ dispatch: false })
logThisEffect$: Observable<void> = this.actions$
.ofType(dataActions.LOG_THIS_EFFECT)
.pipe(map(() => console.log('logThisEffect$ called')));
选择的答案不再适用于 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,
) {
}
}
从 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)
);
如果您不想派发一个动作,那么只需将 dispatch
设置为 false:
@Effect()
foo$ = createEffect(() =>
this.actions$.pipe(
ofType(Actions.FOO),
map(t => [])
),
{ dispatch: false }
);
在 "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)))
)
)
)
);