I have a PolicyGuard
with a method canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
.
In canActivate
I create an observable, and inside of this observable I subscribe to an Observable that I retrieve from my AbilityService
.
The observable I retrieve from AbilityService
listens for changes to a users "policies"/"abilities".
This gets pretty messy when I am making changes to a user's "policies" and pushing those changes to the client using Socket.io
as page re-direction to the home page can happen when I don't want it to (One subscription runs obs.next(true)
while another subscription routes to home and runs obs.next(false)
)
Is there a way I can make the subscription unsubscribe when leaving the page that the subscription was meant for?
@Injectable()
export class PolicyGuard implements CanActivate {
constructor(protected router: Router, private abilityService: AbilityService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
console.log("PolicyGuard() - canActivate()");
return new Observable<boolean>(obs => {
const observable = this.abilityService.getAbility();
observable.subscribe(ability => {
const can = ability.can(route.data.action, route.data.subject);
if (can) {
obs.next(true);
}
else {
this.router.navigate(['/home']);
obs.next(false);
}
});
});
}
}
CodePudding user response:
You have currently created an additional Observable which is in my opinion not required. You could simply return this.abilityService.getAbility()
and transform the return value with the RxJS map
operator. This way Angular would take over and handle the subscription from your Observable.
This would look like this:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
console.log("PolicyGuard() - canActivate()");
return this.abilityService.getAbility().pipe(
map(ability => {
const can = ability.can(route.data.action, route.data.subject);
if (!can) {
this.router.navigate(['/home']);
}
return can;
});
);
}