Angular 2更新全局状态是更新特定状态的副作用 [英] Angular 2 update global state as a side effect of updating a certain state
问题描述
我想设置全局状态,同时还要从api请求数据并将其存储在该状态中,但要存储在全局状态以外的其他位置.
I want to achieve setting a global state while also requesting data from an api and storing that in the state as well, but in another location than the global state.
我称这种效果(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}}))
现在我想做的是这样的:
Now what I want to do is something like this:
@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
)的呼叫:
As you can see we're dispatching a call to the 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
.但是,此解决方案既麻烦又行不通,因为它破坏了效果这一简单事实(无论出于何种原因,我认为这是因为我在效果内调用了dispatch).
Which would mean that I update the global state isLoading
before and after we make an http request. However, this solution is both messy and does not work because of the simple fact that it breaks the effect (for whatever reason, I think it's because I call dispatch within the effect).
最好是我想创建一个监听SET_LOADING_STATE
的效果,然后调用globalReducer
本身,而不是让models$
效果直接实现.
Preferably I would like to create another effect which listens to SET_LOADING_STATE
which then calls the globalReducer
itself, rather than letting the models$
effect do it directly.
类似的事情(在global.effects.ts
中):
@Effect() loadingState$: Observable<Action> = this.actions$
.ofType(SET_LOADING_STATE)
.do(() => ({type: SET_LOADING_STATE, payload: thePayloadThatWasSent}))
但是有两个问题:
- 我不知道如何访问效果中发送的有效载荷.
- 我不知道如何从
models$
效果中调用该效果.
- I don't know how to access a sent payload in an effect.
- I don't know how to call that effect from within the
models$
effect.
总的来说,我对如何实现自己想要的东西感到非常困惑,据我所知,还没有任何示例.
Overall I'm just really confused on how to achieve what I want and there aren't any examples of this as far as I've been able to find.
如果您看这张图片,我想在更新models
时更新global.isLoading
:
If you look at this image, I want to update global.isLoading
when I update models
:
实现我想要的最好的方法是什么?
What would be the best way to achieve what I want?
推荐答案
将isLoading
指示符存储在中央位置类似于有时使用错误信息进行的操作.一种用于存储中心错误的解决方案涉及使用化简器,该化简器会忽略操作的类型,仅查看它们是否包含error
属性.
Storing an isLoading
indicator in a central place is a similar to what is sometimes done with error information. One solution for storing a central error involves using a reducer that ignores actions' types and looks only to see if they contain an error
property.
如果要为效果的动作类型采用合适的命名方案,则可以使用isLoading
做很多相同的事情.
If you were to adopt a suitable naming scheme for your effects' action types, you could do much the same thing with isLoading
.
一种可能的命名方案可能是:
One possible naming scheme could be:
SOME_ACTION_REQUEST
SOME_ACTION_RESPONSE
SOME_ACTION_ERROR
使用这种方案,以下减速器将检查动作类型并相应地设置isLoading
状态:
With such a scheme, the following reducer would examine the action types and set the isLoading
state accordingly:
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
值假定您没有并发异步效果,因此,如果出现问题,可以扩展reducer使其使用计数器.
Using a boolean
value for isLoading
assumes that you would not have concurrent asynchronous effects, so if that's an issue, you could extend the reducer to use a counter instead.
如果您通过这种方式进行连接,则isLoading
指示器不需要了解有关单个效果的任何信息,反之亦然.
If you wire things up this way, the isLoading
indicator doesn't need to know anything about individual effects and vice versa.
这篇关于Angular 2更新全局状态是更新特定状态的副作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!