我很好奇是否有任何方法可以确保在返回多个操作时@ngrx/effects
中的操作顺序作为对其他操作的响应。
ActionA => emit ActionB (=> emit async ActionB1, ActionB2) and then ActionC
我希望实现ActionA
,ActionB
,ActionB1
,ActionB2
,ActionC
的序列。
可以使用concatMap
,但似乎无法确保在发出C之前处理动作B1和B2。
真实世界的例子:
@Effect()
oauthLoginAsSomeoneElse$: Observable<Action> = this.actions$
.ofType<AuthActions.OAuthLoginAsSomeoneElse>(AuthActions.OAUTH_LOGIN_AS_SOMEONE_ELSE)
.pipe(
concatMap(action => [
// First logout
new AuthActions.OAuthLogout(),
// Then login again
new AuthActions.OAuthLogin({redir: action.payload.redir})
])
);
@Effect({dispatch: false})
oauthLogin$: Observable<Action> = this.actions$
.ofType<AuthActions.OAuthLogin>(AuthActions.OAUTH_LOGIN)
.pipe(
map(action => oauthRedir.start(
this.authEndpoint + '/oauth/authorize',
this.authClientId,
this.authRedirectUri,
this.appBaseHref,
action.payload.redir,
))
);
@Effect()
oauthLogout$: Observable<Action> = this.actions$
.ofType<AuthActions.OAuthLogout>(AuthActions.OAUTH_LOGOUT)
.pipe(
switchMap(action =>
this.http.post(`${this.authEndpoint}/logout`, null, {withCredentials: true}).pipe(
map(responseData => new AuthActions.SessionTerminate()),
catchError((err: HttpErrorResponse) => {
return of(new RouterActions.Go({path: ['/']}));
}),
)
)
);
您可能希望,在调度OAuthLoginAsSomeoneElse
时,与OAuthLogout
操作相关的所有内容都将完成(包括@Effect()
发出的操作中的一些异步内容),然后再次发出OAuthLogin
。我的意思是,首先处理第一个根动作及其子节点,然后处理下一个发出的根动作。
您知道如何实现这种情况吗?我目前的解决方法是将下一个动作作为参数发送到OAuthLogout
,但这并不能很好地扩展,并且很快就会变得非常复杂。
答案 0 :(得分:0)
有些晚,但仍是最新的。您可以使用效果来确定触发操作的顺序,即使没有附带HTTP请求或其他请求也是如此。这样,您可以轻松设置一系列操作。使用最新的NgRX效果语法,其外观将类似于以下内容:
首先设置一个在actionB
之后触发actionA
的效果。
effect1$ = createEffect(() => this.actions$.pipe(
ofType(actionA),
mapTo(actionB())
));
在执行动作B之后,您可以定义它应该触发actionB1
。您还可以传递有效载荷。
effect2$ = createEffect(() => this.actions$.pipe(
ofType(actionB),
map(payload => actionB1(payload)
));
当然应该有适当的效果名称,依此类推。但希望您能明白这一点。只需使用ofType
和map
指定顺序即可。
以您的真实示例为例,您还需要“响应”操作,例如loginSuccess
,loginFailed
,logoutSuccess
等。在适当位置使用这些操作即可以上方法来创建明确定义的动作序列。