Angular ngrx:有副作用的守卫
Angular ngrx: guards with side-effect
我最近很抱歉,如果它是某个问题的重复,但我找不到解决我的问题的方法。
我有守卫,现在我需要从调用 http 服务并将用户重定向到错误状态的副作用中捕获错误。尝试添加 catchError
但如果服务器端出现错误,我什至不会去那里。
guard.ts
canActivate(): Observable<boolean> {
return this.store
.select(fromDataStore.getDatasLoaded)
.pipe(
withLatestFrom(this.store.select(fromDataStore.getDataLoading)),
map(([loaded, loading]) => {
if (!loaded && !loading) {
this.store.dispatch(new fromDataStore.LoadData());
}
return loaded;
}),
filter(loaded => loaded),
take(1),
catchError(error => {
// redirect user to error state
})
);
}
effect.ts
@Effect() loadData$: Observable<Action> = this.actions$.ofType(DataActionTypes.LoadData)
.pipe(
mergeMap(() =>
this.dataApiService.loadData()
.pipe(
map(data => ({
type: DataActionTypes.LoadDataSuccess,
payload: data
})),
catchError(() => of({ type: DataActionTypes.LoadDataFailure }))
)
)
);
reducer.ts
case DataActionTypes.LoadData: {
return {
...state,
data: {
...state.data,
isLoading: true
}
};
}
case DataActionTypes.LoadDataSuccess: {
return {
...state,
data: {
...dataAdapter.addMany(action.payload, state.data),
isLoaded: true,
isLoading: false
}
};
}
case DataActionTypes.LoadDataFailure: {
return {
...state,
data: {
...state.data,
isLoaded: true,
isLoading: false
}
};
}
default: {
return state;
}
当你在reducer中处理LoadDataFailure时,你可以将错误添加到状态中。
在守卫中你可以添加一个 withLatestFrom 和 select 那部分状态,带有错误。而不是catchError,这里没有错误所以它不会捕获任何东西。
如果没有错误,您可以导航到该页面,如果有错误,则将用户重定向到您需要的页面。
您也可以稍微重构一下代码,比如总是在守卫进入时触发加载操作,将 if 语句移到外面,并使用 isDataLoaded 流。
类似于:
this.store.dispatch(new fromDataStore.LoadData());
return this.store
.select(fromDataStore.getDatasLoaded)
.filter(Boolean),
.withLatestFrom(fromDataStore.getError)
...
我最近很抱歉,如果它是某个问题的重复,但我找不到解决我的问题的方法。
我有守卫,现在我需要从调用 http 服务并将用户重定向到错误状态的副作用中捕获错误。尝试添加 catchError
但如果服务器端出现错误,我什至不会去那里。
guard.ts
canActivate(): Observable<boolean> {
return this.store
.select(fromDataStore.getDatasLoaded)
.pipe(
withLatestFrom(this.store.select(fromDataStore.getDataLoading)),
map(([loaded, loading]) => {
if (!loaded && !loading) {
this.store.dispatch(new fromDataStore.LoadData());
}
return loaded;
}),
filter(loaded => loaded),
take(1),
catchError(error => {
// redirect user to error state
})
);
}
effect.ts
@Effect() loadData$: Observable<Action> = this.actions$.ofType(DataActionTypes.LoadData)
.pipe(
mergeMap(() =>
this.dataApiService.loadData()
.pipe(
map(data => ({
type: DataActionTypes.LoadDataSuccess,
payload: data
})),
catchError(() => of({ type: DataActionTypes.LoadDataFailure }))
)
)
);
reducer.ts
case DataActionTypes.LoadData: {
return {
...state,
data: {
...state.data,
isLoading: true
}
};
}
case DataActionTypes.LoadDataSuccess: {
return {
...state,
data: {
...dataAdapter.addMany(action.payload, state.data),
isLoaded: true,
isLoading: false
}
};
}
case DataActionTypes.LoadDataFailure: {
return {
...state,
data: {
...state.data,
isLoaded: true,
isLoading: false
}
};
}
default: {
return state;
}
当你在reducer中处理LoadDataFailure时,你可以将错误添加到状态中。
在守卫中你可以添加一个 withLatestFrom 和 select 那部分状态,带有错误。而不是catchError,这里没有错误所以它不会捕获任何东西。
如果没有错误,您可以导航到该页面,如果有错误,则将用户重定向到您需要的页面。
您也可以稍微重构一下代码,比如总是在守卫进入时触发加载操作,将 if 语句移到外面,并使用 isDataLoaded 流。
类似于:
this.store.dispatch(new fromDataStore.LoadData());
return this.store
.select(fromDataStore.getDatasLoaded)
.filter(Boolean),
.withLatestFrom(fromDataStore.getError)
...