Reputation: 668
The following code is what I have and it works.
canActivate(route: ActivatedRouteSnapshot): Observable<UrlTree | boolean> {
return new Observable<UrlTree | boolean>((observer) => {
this._authorizedStore
.select(selectProfile)
.pipe(take(1))
.subscribe((profile) => {
if (!profile) {
this._authorizedStore.dispatch(
AuthorizedActions.loadProfile({ userId: this._authenticationApi.getUser().id }),
);
}
this._authorizedStore
.select(selectAuthorizedState)
.pipe(first((state) => !!state.profile))
.subscribe((state) => {
if (state.profile.profiles.length > 0) {
observer.next(true);
} else {
observer.next(this.router.createUrlTree(['./settings']));
}
observer.complete();
});
});
});
}
What I wanted was to figure out a better and prettier way to do the same thing. Basically I want to first check if I have a profile, if I don't have it I want to trigger the request and then wait. One thing to note, as you can see I'm using Ngrx, so if I don't take(1) at the beginning I would get an infinite loop (not profile, make request, not profile, make request...).
Any ideas?
Upvotes: 0
Views: 62
Reputation: 10525
You can use tap
and switchMap
. Like this:
this._authorizedStore
.select(selectProfile)
.pipe(
take(1),
tap(profile => {
if (!profile) {
this._authorizedStore.dispatch(
AuthorizedActions.loadProfile({ userId: this._authenticationApi.getUser().id }),
);
}
}),
switchMap(profile => this._authorizedStore.select(selectAuthorizedState).pipe(first(state => !!state.profile)))
)
.subscribe(state => {
if (state.profile.profiles.length > 0) {
observer.next(true);
} else {
observer.next(this.router.createUrlTree(['./settings']));
}
observer.complete();
});
You can also shorten your whole code to this:
canActivate(route: ActivatedRouteSnapshot): Observable<UrlTree | boolean> {
return this._authorizedStore
.select(selectProfile)
.pipe(
take(1),
tap(profile => {
if (!profile) {
this._authorizedStore.dispatch(
AuthorizedActions.loadProfile({ userId: this._authenticationApi.getUser().id }),
);
}
}),
switchMap(profile => this._authorizedStore.select(selectAuthorizedState)),
first(state => !!state.profile),
map(state => state.profile.profiles.length > 0 ? true : this.router.createUrlTree(['./settings']))
);
}
Upvotes: 2