问题描述
减速器:
list_of_str = ["Em","Bsus4","F7","Fis7"]
print([item[0:2] if len(item)>1 and item[1] == "m" else item[0:3] if len(item)>2 and item[1:3] == "is" else item[0] for item in list_of_str])
效果:
['Em','B','F','Fis']
component.ts:
export const reducer = (state = initialstate,action: any) => {
switch (action.type) {
case ADD_USER: {
return {
...state,userAdded: false
}
},case ADD_USER_SUCCESS: {
return {
...state,user: action.payload
userAdded: true
}
},case ADD_USER_FAIL: {
return {
...state,userAdded: false
}
}
}
}
单击该方法,将调度一个动作,然后执行一个效果,我的情况是api调用是成功的,并且还调度了一个成功动作(在我的reducer中,我将标志设置为true),从click方法调度的AddUser操作,如果API返回成功响应,我正在订阅标志login$ = createEffect(() =>
this.actions$.pipe(
ofType(UserAction.ADD_USER),exhaustMap(action =>
this.userService.addUser("USER").pipe(
map(user => UserAction.AddUserSuccess({ "user" })),catchError(error => of(UserAction.AddUserFail({ error })))
)
)
)
);
以将用户导航到onClickAddUser(): void {
this.store.dispatch(new AddUser('USER'));
this.store.pipe(select(getUser),take(1)).subscribe((isUserAdded) => {
if(isUserAdded) {
this.router.navigateByUrl('/success'); // Expectation is to navigate to success page
} else {
this.router.navigateByUrl('/home'); // for first time it's always going to home screen even the success action being dispatched and the value been set to true.
}
});
}
屏幕,在我的情况下,我正在订阅标记,因为它没有在商店中更新,因此用户导航到主屏幕(但是期望是因为API成功,所以导航到成功屏幕)。是否有可能等待存储中的值更新然后订阅它,或者是否有最佳实践来处理这种情况?
一旦派发成功操作,我可以编写一种效果来导航用户,但是我的意思是,一旦标志设置为true,我确实有其他功能可以处理,因此必须在组件中完成所有操作。
解决方法
事件的顺序如下:
- 您调度了
AddUser
操作
this.store.dispatch(new AddUser('USER'));
- 调用reducer,状态被突变,并且
userAdded
设置为false
case ADD_USER: {
return {
...state,userAdded: false
}
},
- 将调用选择器并通知订阅者,但您尚未有任何订阅
- 调用效果
ADD_USER
,并将异步请求发送到userService
login$ = createEffect(() =>
this.actions$.pipe(
ofType(UserAction.ADD_USER),exhaustMap(action =>
this.userService.addUser("USER").pipe(
map(user => UserAction.AddUserSuccess({ "user" })),catchError(error => of(UserAction.AddUserFail({ error })))
)
)
)
);
- 您通过管道中的
getUser
运算符订阅了take(1)
选择器
this.store.pipe(select(getUser),take(1)).subscribe((isUserAdded) => {
if(isUserAdded) {
this.router.navigateByUrl('/success');
} else {
this.router.navigateByUrl('/home');
}
});
- 选择器从存储区
userAdded
返回false
标志的值,调用您的回调函数,take(1)
运算符取消订阅 - 路由器导航到“ / home”
- 返回来自
userService
的响应,并将userAdded
标志设置为true
,但您的订阅已被取消
如果您想直接在component.ts
中找到简单的解决方案,只需尝试订阅take(2),skip(1)
:
this.store.pipe(select(getUser),take(2),skip(1)).subscribe((isUserAdded) => {
if(isUserAdded) {
this.router.navigateByUrl('/success');
} else {
this.router.navigateByUrl('/home');
}
});
,
您是否不能只在您的效果fn中返回两个动作,例如UserAddedSuccess并在catchError UserAddedFail中编写另一个效果,该效果将侦听useraddedsuccess动作并在成功后重定向所需的页面,就第一个效果catcherror返回UserAddedFail动作和相同的过程吗?
,我想您可以调度多个动作,您必须创建单独的动作来处理路由。
login$ = createEffect(() =>
this.actions$.pipe(
ofType(UserAction.ADD_USER),exhaustMap(action =>
this.userService.addUser("USER").pipe(
switchMap(user => [
UserAction.AddUserSuccess({ "user" }),routeAction.routeto('success')
]),catchError(error => [
UserAction.AddUserFail({ error }),routeAction.routeto('Home');
])
)
)
)
);