Angular 2 更新全局状态作为更新特定状态的副作用
Angular 2 update global state as a side effect of updating a certain state
我想实现设置全局状态,同时还从 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}))
但这有两个问题:
- 我不知道如何在效果中访问已发送的负载。
- 我不知道如何从
models$
效果中调用该效果。
总的来说,我真的很困惑如何实现我想要的,而且就我所能找到的而言,没有任何这方面的例子。
如果你看这张图,我想在更新models
时更新global.isLoading
:
实现我想要的最好方法是什么?
将 isLoading
指标存储在中央位置类似于有时对错误信息所做的操作。一个 涉及使用忽略操作类型的缩减器,只查看它们是否包含 error
属性.
如果您要为效果的动作类型采用合适的命名方案,您可以对 isLoading
做很多相同的事情。
一种可能的命名方案可以是:
SOME_ACTION_REQUEST
SOME_ACTION_RESPONSE
SOME_ACTION_ERROR
使用这样的方案,以下减速器将检查操作类型并相应地设置 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;
}
}
为 isLoading
使用 boolean
值假设您不会有并发的异步效果,所以如果这是一个问题,您可以扩展减速器以使用计数器。
如果您以这种方式连接,isLoading
指标不需要知道任何关于单个效果的信息,反之亦然。
我想实现设置全局状态,同时还从 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}))
但这有两个问题:
- 我不知道如何在效果中访问已发送的负载。
- 我不知道如何从
models$
效果中调用该效果。
总的来说,我真的很困惑如何实现我想要的,而且就我所能找到的而言,没有任何这方面的例子。
如果你看这张图,我想在更新models
时更新global.isLoading
:
实现我想要的最好方法是什么?
将 isLoading
指标存储在中央位置类似于有时对错误信息所做的操作。一个 error
属性.
如果您要为效果的动作类型采用合适的命名方案,您可以对 isLoading
做很多相同的事情。
一种可能的命名方案可以是:
SOME_ACTION_REQUEST
SOME_ACTION_RESPONSE
SOME_ACTION_ERROR
使用这样的方案,以下减速器将检查操作类型并相应地设置 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;
}
}
为 isLoading
使用 boolean
值假设您不会有并发的异步效果,所以如果这是一个问题,您可以扩展减速器以使用计数器。
如果您以这种方式连接,isLoading
指标不需要知道任何关于单个效果的信息,反之亦然。