我想实现设置一个全局状态,同时也从api请求数据并将其存储在状态中,但是在另一个位置而不是全局状态。
我正在调用此效果(models.effects.ts
):
@Effect() models$: Observable<Action> = this.actions$
.ofType(GET_MODELS)
.switchMap(() => this.modelsApi.getModels())
.map(models => ({type: SET_MODELS, payload: models}))
.catch((err: any) => Observable.of({type: GET_FAILURE, payload: {error: err}}))
现在我想做的是这样的事情:
@Effect() models$: Observable<Action> = this.actions$
.ofType(GET_MODELS)
.do(() => this.store.dispatch({type: 'SET_LOADING_STATE', payload: true}))
.switchMap(() => this.modelsApi.getModels())
.map(models => ({type: SET_MODELS, payload: models}))
.do(() => this.store.dispatch({type: 'SET_LOADING_STATE', payload: false}))
.catch((err: any) => Observable.of({type: GET_FAILURE, payload: {error: err}}))
您可以看到我们正在拨打globalReducer
(global.reducer.ts
)的电话:
export const GlobalReducer: ActionReducer<any> = (state: IGlobalStorage = {isLoading: false}, action: Action) => {
switch(action.type) {
case SET_LOADING_STATE: return Object.assign({}, state, {
isLoading: action.payload
});
default: return state;
}
}
这意味着我在发出http请求之前和之后更新全局状态isLoading
。然而,这个解决方案既麻烦又不起作用,因为它打破了效果的简单事实(无论出于何种原因,我认为这是因为我在效果中调用了调度)。
我希望创建另一个收听SET_LOADING_STATE
的效果,然后调用globalReducer
本身,而不是让models$
效果直接执行。
这样的事情(来自global.effects.ts
内):
@Effect() loadingState$: Observable<Action> = this.actions$
.ofType(SET_LOADING_STATE)
.do(() => ({type: SET_LOADING_STATE, payload: thePayloadThatWasSent}))
但是有两个问题:
答案 0 :(得分:3)
将isLoading
指标存储在中央位置与有时使用错误信息进行的操作类似。一个the API docs涉及使用忽略动作的减速器。类型和外观只是为了查看它们是否包含error
属性。
如果你要为你的效果采用合适的命名方案&#39;动作类型,你可以用isLoading
做同样的事情。
一种可能的命名方案可能是:
SOME_ACTION_REQUEST
SOME_ACTION_RESPONSE
SOME_ACTION_ERROR
使用这样的方案,以下reducer将检查操作类型并相应地设置isLoading
状态:
export function isLoadingReducer(state: boolean = false, action: Action): boolean {
if (/_REQUEST$/.test(action.type)) {
return true;
} else if (/(_RESPONSE|_ERROR)$/.test(action.type)) {
return false;
} else {
return state;
}
}
对boolean
使用isLoading
值假设您不会有并发异步效果,因此如果这是一个问题,您可以扩展reducer以使用计数器。
如果以这种方式连接,isLoading
指示器不需要知道任何有关个别效果的信息,反之亦然。