如果这是一个简单的答案,请原谅我。我有一个复杂的登录逻辑,在用户拥有完整的配置文件之前,需要几次调用。如果某个步骤失败,则不应破坏应用程序-用户只是无法获得一些补充信息。
我要实现的流程是这样的:
Revalidate
。Revalidate
会同时调用RevalidateSuccess
和ProfileGet
(通过提取来增强用户状态)。ProfileGetSuccess
。为节省大量代码,存在操作(这是一个巨大的文件)。
该应用开始执行操作:this._store.dispatch(new Revalidate())
从那里开始,我们将产生以下效果:
@Effect()
public Revalidate: Observable<any> = this._actions.pipe(
ofType(AuthActionTypes.REVALIDATE),
map((action: Revalidate) => action),
// This promise sets 'this._profile.currentProfile' (an Observable)
flatMap(() => Observable.fromPromise(this._auth.revalidate())),
// Settings are retrieved as a promise
flatMap(() => Observable.fromPromise(this._settings.get())),
switchMap(settings =>
// Using map to get the current instance of `this._profile.currentProfile`
this._profile.currentProfile.map(profile => {
const onboarded = _.attempt(() => settings[SettingsKeys.Tutorials.Onboarded], false);
return new RevalidateSuccess({ profile: profile, onboarded: onboarded });
}))
);
//Since I couldn't get it working using concatMap, trying NOT to call two actions at once
@Effect()
public RevalidateSuccess: Observable<any> = this._actions.pipe(
ofType(AuthActionTypes.REVALIDATE_SUCCESS),
mapTo(new ProfileGet)
);
@Effect()
public ProfileGet: Observable<any> = this._actions.pipe(
ofType(AuthActionTypes.PROFILE_GET),
// We need to retrieve an auth key from storage
flatMap(() => Observable.fromPromise(this._auth.getAuthorizationToken(Environment.ApiKey))),
// Now call the service that gets the addt. user data.
flatMap(key => this._profile.getCurrentProfile(`${Environment.Endpoints.Users}`, key)),
// Send it to the success action.
map(profile => {
console.log(profile);
return new ProfileGetSuccess({});
})
);
减速器:
export function reducer(state = initialState, action: Actions): State
{
switch (action.type) {
case AuthActionTypes.REVALIDATE_SUCCESS:
console.log('REVALIDATE_SUCCESS');
return {
...state,
isAuthenticated: true,
profile: action.payload.profile,
onboarded: action.payload.onboarded
};
case AuthActionTypes.PROFILE_GET_SUCCESS:
console.log('PROFILE_GET_SUCCESS');
return { ...state, profile: action.payload.profile };
case AuthActionTypes.INVALIDATE_SUCCESS:
return { ...state, isAuthenticated: false, profile: undefined };
default:
return state;
}
}
正如标题所述,调度动作是无限运行的。谁能指出我正确的方向?
答案 0 :(得分:0)
答案就在这里
this._profile.currentProfile.map
必须为this._profile.currentProfile.take(1).map
。问题不是我的所有动作都被调用的事实,而是因为我是在可观察对象上运行一个动作,所以我想每次有人触摸可观察对象时,它都会重新运行该动作,而这恰好是无限次。
此外,我能够重构动作存储,以便摆脱其他动作来调用以获取用户的其余数据,而订阅this._profile.currentProfile
并调用基于非效果的动作,ProfileSet
,当可观察值改变时。这让我删除了6个动作(因为它们是异步调用并且需要成功/失败的伴随动作),所以这是一个很大的胜利。