我有@ ngrx/store和效果正常,但是,我刚刚意识到会有很多API调用(在效果中),如果其中任何一个返回401错误,我应该将用户重定向到登录页面.我的问题是:我不想在每一个效果中都检查一下,这对同样的事情来说是一个额外的代码.比方说,我有一个像这样的代码:
样本效果
@Effect() getMe$ = this.actions$
.ofType(GET_ME)
.map(action => action.payload)
.switchMap(payload => this.userService.me()
.map(res => ({ type: GET_ME_SUCCESS, payload: res }))
.catch(() => Observable.of({ type: GET_ME_FAILURE }))
);
Run Code Online (Sandbox Code Playgroud)
userService.me()
me(): Observable<User> {
return this.apiService.get(`/auth/me`);
}
Run Code Online (Sandbox Code Playgroud)
apiService.get()
get(endpoint: string): Observable<any> {
return this.http.get(`${this.base}${endpoint}`, this.options())
.map(res => res.json());
}
Run Code Online (Sandbox Code Playgroud)
这很好用,但我不知道如何在API返回401时处理这种情况.在这种情况下,我应该在哪里全局重定向用户?我应该为该案件制定行动吗?那我应该在哪里发送这个动作呢?或者我完全错了吗?
任何正确方向的帮助将不胜感激!
我正在使用ngrx构建ng2应用程序.启动应用程序时,会调用Web服务来获取初始数据,一旦获取此数据,我就会创建一个INIT_DONE操作.
我的州看起来像这样:
export interface State {
documents: Document[];
selectedDocument: Document
}
Run Code Online (Sandbox Code Playgroud)
当我转到页面/ mypage/456,其中456是一个url参数时,我需要获取一些获取的数据,所以我得到这样的URL参数:
ngOnInit() {
this.paramSubscription = this.route.params
.select<string>('id')
.map((id) => new SelectAction(id))
.subscribe(this.store);
}
Run Code Online (Sandbox Code Playgroud)
所述SELECT_ACTION发现在所取得的数据,并设置在元件selectedDocument.问题是SELECT_ACTION是在INIT_DONE之前创建的,并且此时documents为空.
如何在加载页面之前等待INIT_DONE?
首先,我正在使用:
现在,类似于反应现实世界的例子,我有一片专用于实体的状态,这实际上是denormalize()normalizr工作方法的一个要求,因为文章可以有一个author,或者media都可以是实体本身.
这意味着当我选择一个user来自我的状态的单个时,我正在抓住这个全局的实体片段,我的选择器看起来像这样
export const getOne = createSelector(
getAllEntities,
getDetailId,
(entities, id) => denormalize(id, schema, entities)
);
Run Code Online (Sandbox Code Playgroud)
然后从ngrx/store"选择"
state.map(getOne).distinctUntilChanged()
Run Code Online (Sandbox Code Playgroud)
现在填写我的表格我这样做(半伪代码)
class Cmp {
form = new FormGroup({ /* whatever */});
user$ = this._store.map(getOne).distinctUntilChanged();
constructor(private _store: Store<AppState>) {
this.user$.subscribe((data) => {
this.form.patchValue(data);
});
}
}
Run Code Online (Sandbox Code Playgroud)
结合重新选择和map/distincUntilChanged我几乎可以在任何实体更改时获得新的更新,所以请考虑这种情况..
text"FormControlsubscribe触发(因为全局实体切片已更改)并覆盖您在编辑时更改的任何值,使用当前存储中的值(旧值)..这个websocket有很多不同的情况可以导致更新更新.
在redux世界中是否有任何模式可以解决这个问题,或者ngrx世界中的任何人都必须处理这个问题?我想到的唯一明智的事情就是在输入时保存商店的任何价值,这需要挂钩角度反应形式来存储,这是屁股的巨大痛苦,并且ngrx /表格不会很快到来.但我确信有人必须已经提出了一些简单的解决方案.
谢谢!
(你可以阅读关于 …
我正在使用HTTP Patch请求更新一组实体到远程后端.来自后端的响应仅包括更新的实体(即,不是所有实体).
我使用实体状态适配器设置我的reducer并用于updateMany更新我的实体:
case settings.SettingsActionTypes.UpdateSettingsSuccess: {
return {
...state,
...adapter.updateMany(action.payload.map((category) => Object.assign({}, {id: category.name, changes: category})), state),
loaded: true,
loading: false,
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这会更新接收更新的实体,但它会删除后端未返回的所有其他实体.
有没有办法告诉ngrx只更新包含在action.payload?中的实体?
在我用Angular开发的应用程序中,我使用Firebase Authentication服务进行身份验证,在我的应用程序登录时,状态以正确的方式更改,根据我的需要保持表单的所有状态。
当我登录时,我在Redux DevTools中注意到我的应用程序的"auth"状态具有身份验证状态,因此我可以从经过身份验证的用户访问数据。
当我导航到系统上的任何其他页面时,"auth"身份验证状态在发生调用的事件后消失,"@ngrx/store/update-reducers"并且我的系统上不再有身份验证状态信息。
为什么会发生这种情况?为什么会"@ngrx/store/update-reducers"被调用?
我有一个"store"位于"src/app"树内文件夹中的文件。在这个文件中,我有我在根模块中创建的所有减速器"app.module"。
索引.ts:
import { ActionReducerMap, createFeatureSelector } from '@ngrx/store';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Params } from '@angular/router';
import * as fromRouter from '@ngrx/router-store';
import * as fromAuth from '../reducers/auth.reducer';
import * as fromMessenger from '../reducers/messenger.reducer';
export interface RouterStateUrl {
url: string;
queryParams: Params;
params: Params;
}
export interface StateApp {
auth: fromAuth.AuthState; …Run Code Online (Sandbox Code Playgroud) 我目前正在规划一个大规模的 Angular 6 应用程序,并试图找到一种最适合团队需求的方法来处理副作用。
我意识到在 Ngrx 生态系统中最常用的方法是使用ngrx/effects库,我想知道与thunk方法相比使用它有什么优势,thunk方法似乎是 React 最流行的方法应用。
我的想法是将所有引起副作用的逻辑隔离在一个地方,我总是倾向于将它们隔离在 Action Creators 范围内。将所有副作用逻辑移动到不同的“抽象层”感觉就像会增加编写副作用动作的开销,而没有可观的附加值,因为大多数“强烈逻辑”动作用于处理副作用。
有没有其他理由支持效果而不是 thunk?Angular 中的 ngrx 和 React 的经典 Redux 之间有什么根本区别,这使得 ngrx/effect 成为更好的选择吗?
我正在尝试@Effect()为我的操作创建一个。当我使用 type 运行 action 时,AuthenticationUserLoad出现错误。
ERROR Error: Effect "AuthenticationEffects.getUser$" dispatched an invalid action: [object Object]
Run Code Online (Sandbox Code Playgroud)
这是我的Effect代码
@Effect()
getUser$ = this.actions$.pipe(
ofType(AuthenticationUserActions.AuthenticationUserTypes.AuthenticationUserLoad),
map((action) => {
return this.authService.getUser().pipe(
map((user: User) => new AuthenticationUserActions.AuthenticationUserLoadSuccess({user})),
catchError(error => of(new AuthenticationUserActions.AuthenticationUserLoadFailure({error})))
);
})
);
Run Code Online (Sandbox Code Playgroud)
更新
我改变map了switchMap,它的工作原理。
@Effect()
getUser$ = this.actions$.pipe(
ofType(AuthenticationUserActions.AuthenticationUserTypes.AuthenticationUserLoad),
switchMap((action) => {
return this.authService.getUser().pipe(
map((user: User) => new AuthenticationUserActions.AuthenticationUserLoadSuccess({user})),
catchError(error => of(new AuthenticationUserActions.AuthenticationUserLoadFailure({error})))
);
})
);
Run Code Online (Sandbox Code Playgroud)
也许我不明白 map 和 switchMap 之间的区别。
我有一个称为动物的功能减速器(切片减速器)。我想将这些减速器拆分为哺乳动物、鸟类、鱼类等。这部分很简单,因为我可以简单地使用ActionReducerMap.
现在假设哺乳动物的减速器状态很大,我想将其拆分为几个较小的减速器,即猫的家庭、狗的家庭等。 ActionReducerMap 不返回减速器并且不可嵌套。我尝试在网上搜索解决方案或示例,但找不到。简而言之,我的问题是如何制作多级嵌套减速器。
export interface AnimalsState{
mammals: fromMammals.mammalsState;
birds: fromBirds.birdsState;
}
export const reducers: ActionReducerMap<AnimalsState> = {
mammals: fromMammals.reducer,
birds: fromBirds.reducer
};
Run Code Online (Sandbox Code Playgroud)
我想将哺乳动物减速器拆分为更小的减速器。
我有一组项目,我想在每个元素上进行 HTTP 调用,等待它完成,然后再进行一次调用,一次只调用一个。
我试过:
index(item) {
return this.service.index(item).pipe(
map(response => {
// handle success case
}),
catchError(error => {
// handle error case
})
)
}
async processArray(array) {
const promises = array.map(item => this.index(item));
await Promise.all(promises);
}
proccessArray(array);
Run Code Online (Sandbox Code Playgroud)
还有 NGRX 效果:
@Effect()
effect$ = this.actions$.pipe(
ofType<action>(actionTypes.action),
mergeMapTo(this.store.select(getMyArray)),
flatMap((request: any[]) => {
return zip(...request.map(item => {
return this.service.index(item).pipe(
map(response => {
// handle success case
}),
catchError(error => {
// handle error case
})
)
}))
}),
);
Run Code Online (Sandbox Code Playgroud)
也试着做它for …
我在这里就 ngrx 效果与您联系,我尝试做的是有一个函数登录,它可以分配一个动作类型登录,并且对这个动作的影响将使用我的服务进行 api 调用。在此返回令牌之后,我想调度另外两个操作,一个是 getUserMenu 类型,另一个是 getUserInfo 类型。这两个动作的类型不同,效果也不同。
我最后有 3 个商店:一个用于令牌,一个用于用户信息,一个用于菜单信息
我试过这样的事情:
login = createEffect(
() =>
this.actions$
.pipe(
ofType(authLogin),
tap(action => {
console.log("EFFECT LOGINNNN");
return this.authService.postLogin(action.username,
action.password).pipe(
map((data: any) => {
console.log("AUTHTHHTHTH DATATA ", data);
let props = data.token;
let payload = {
token: data.token,
isAuthenticated: true
}
this.store.dispatch(moMenuHttpGetListAction({US_ID: action.username}));
this.store.dispatch(userHttpGetInfoAction({US_ID:action.username}));
this.localStorageService.setItem(AUTH_KEY, payload);
}))
})
),
{ dispatch: true }
);
Run Code Online (Sandbox Code Playgroud)
如果我设置 dispatch false 登录工作但没有调用获取用户信息和用户菜单的方法但是当我设置 dispatch true 我有 infinit 循环同样的效果,动作 moMenuHttpGetListAction 看起来像这样:
moMenuHttpGetListEffect = createEffect(
() => this.actions$.pipe( …Run Code Online (Sandbox Code Playgroud) ngrx ×10
angular ×9
ngrx-effects ×3
redux ×3
javascript ×2
ngrx-store ×2
rxjs ×2
typescript ×2
firebase ×1
ngrx-entity ×1
redux-thunk ×1