这是一个具有在当前代码中重复多次的模式的代码
loadBasicStateInfo$ = createEffect(() => this.actions$.pipe(
ofType(actions.loadBasicStateInfo),
switchMap(args => this.configurationService.getBasicStateInfo()
.pipe(
map(response => actions.loadBasicStateInfoComplete({ basicStateInfo: new BasicStateInfo(response.result) })),
catchError(() => of(actions.loadBasicStateInfoFailure({ error: 'fail' })))
)
)
));
loadClientServerMinutesOffset$ = createEffect(() => this.actions$.pipe(
ofType(actions.loadClientServerMinutesOffset),
switchMap(args => this.configurationService.getClientServerMinutesOffset()
.pipe(
map(response => actions.loadClientServerMinutesOffsetComplete({ clientServerMinutesOffset: response.result })),
catchError(() => of(actions.loadClientServerMinutesOffsetFailure({ error: 'fail' })))
)
)
));
loadSetting$ = createEffect(() => this.actions$.pipe(
ofType(actions.loadSettings),
switchMap(args => this.configurationService.getSettingsByNamesForUser(args.settingNames)
.pipe(
map(response => actions.loadSettingsCompleted({ settings: response.result })),
catchError(() => of(actions.loadSettingsFailure({ error: 'fail' })))
)
)
));
我对打字脚本很陌生,但我想重构成一些辅助方法,这就是我的起点
import { Actions, createEffect } from '@ngrx/effects';
import { catchError, switchMap } from 'rxjs/operators';
class effectHelper {
public create(act: Actions, type: any, apiCall: any, methodForMap: any, methodForError: any) {
return createEffect(() => act.pipe(
ofType(type),
switchMap(apiCall.pipe(
map(methodForMap)),
catchError(methodForError))
));
}
}
我如何实现像上面这样的通用帮助程序?这可能吗?如何实现这一目标?
更新
action是以这种方式声明的ngrx操作
export const loadClientServerMinutesOffset = createAction('[Configuration] Load Client Server Minutes Offset');
export const loadClientServerMinutesOffsetComplete = createAction('[Configuration] Load Client Server Minutes Offset Completed',
props<{ clientServerMinutesOffset: number }>());
export const loadClientServerMinutesOffsetFailure = createAction('[Configuration] Load Client Server Minutes Offset Failed', props<{ error: any }>());
我对NgRx不太熟悉,但它与我熟悉的Redux非常相似。
我们想要为给定的API调用创建一组三个操作。我们需要知道动作的基本名称,API函数,以及如何从API响应映射到"的数据;完整的";行动,即response => ({ clientServerMinutesOffset: response.result })
我不确定的是Actions
对象来自哪里,以及它应该是父createApiActions
函数的参数还是传递给effect
函数的参数。
使用泛型键入this最令人讨厌的部分是createAction
函数使用类型NotAllowedCheck<P>
来验证参数。如果你只有一个通用的P extends object
,那么你会得到P
不可分配给NotAllowedCheck<P>
的错误。mapResponse
基本上只是(response: Res) => R
,但为了避免这些错误,我不得不将其定义为FunctionWithParametersType<[Res], R & NotAllowedCheck<R>>
。
import { Actions, createEffect, ofType } from "@ngrx/effects";
import { createAction, FunctionWithParametersType, NotAllowedCheck } from "@ngrx/store";
import { catchError, switchMap, map } from "rxjs/operators";
import { of, Observable } from "rxjs";
const createApiActions = <Args extends object, Res, R extends object>(
actions: Actions,
category: string,
apiCall: (args: Args) => Observable<Res>,
mapResponse: FunctionWithParametersType<[Res], R & NotAllowedCheck<R>>
) => {
const pending = createAction(
`[${category}] Pending`,
(args: Args & NotAllowedCheck<Args>) => args
);
const complete = createAction<string, [Res], R>(
`[${category}] Complete`,
mapResponse
);
const failure = createAction(
`[${category}] Failure`,
() => ({ error: "fail" })
);
const effect = createEffect(() =>
actions.pipe(
ofType(pending),
switchMap((args) =>
apiCall(args).pipe(
map((response) => complete(response)),
catchError(() => of(failure()))
)
)
)
);
return {
pending,
complete,
failure,
effect
};
};
该辅助对象创建一组三个动作创建者和效果。效果的结构与以前相同,但现在我们可以用变量替换您的硬编码操作。
你会这样使用它:
const loadSettings = createApiActions(
actions,
'loadSettings',
(args: {settingNames: string[]}) => this.configurationService.getSettingsByNamesForUser(args.settingNames),
(response: SomeType) => ({ settings: response.result }),
)
loadSettings.pending({settingNames: ["someSetting"]})
在这一点上,我已经意识到,在不需要任何参数的情况下,将Args
定义为object
是不起作用的。所以我的类型需要更多的工作。但我将把这件事留给你。