I have a component where I've subscribed to an observable to pull data from Firebase. The relevant subscription code looks something like:
[Note: updated/corrected code below.]
// in my component
ngOnInit() {
// this.af is an injected AngularFire2 instance
this.tasks = this.af.database.list('/tasks')
.subscribe(tasks => this.tasks = tasks);
}
The user must be authenticated to view this component, and I have a route guard in place that ensures this.
However, when I logout I get this error:
Client doesn't have permission to access the desired data
I'm logging out with something like:
// this.auth is an injected FirebaseAuth instance
this.auth.logout();
this.router.navigate(['/login']);
The error occurs before the router navigate
method is called. The problem is that I have this active tasks observer subscription with an open web socket connection that errors out right after the logout
method is called because the user is no longer authenticated.
The tasks subscription and the logout functionality are in different parts of my app. If they were in the same place, I guess I could call the unsubscribe
method on the subscription when I logout. But even so, it seems messy to stick this subscription canceling logic in my logout
method. I'm not quite sure how to deal with this.
How do I handle canceling the subscription to the tasks observer on logout?
Alexander pointed out that I was assigning to the this.tasks
property twice. Good point! This bit of code was incorrect. I wasn't assigning the subscription to a property. The code should have looked like this:
ngOnInit() {
// this.af is an injected AngularFire2 instance
this.af.database.list('/tasks')
.subscribe(tasks => this.tasks = tasks);
}
Thanks for pointing that out, Alexander.
I was able to resolve this partly with Alexander Leonov's comment about unsubscribing with ngOnDestroy
in my component.
Using his code in my tasks component:
ngOnInit() {
this.subscription = this.af.database.list('/tasks')
.subscribe(tasks => this.tasks = tasks);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
The other part of the solution involved subscribing to the AngularFire auth observable in my top level component, the AppComponent. If authenticated, it redirects to one route; if not, it redirects to another route:
this.authService.auth$.subscribe((currentUser) => {
if (currentUser) {
this.router.navigate(['/tasks']);
} else {
this.router.navigate(['/login']);
}
});
When logging out, this subscription is notified and the user is redirected to the login route. This sequence of events ends up triggering the ngOnDestroy
method on my component, which unsubscribes from the tasks AngularFire observable.
You're messed up a bit. You use this.tasks
both to keep a subscription:
this.tasks = this.af.database.list(...)
and later as a task storage:
subscribe(tasks => this.tasks = tasks)
You need to choose one side of the force. :)
To answer your question it would take a bit more information about how your application works. If you initialize connection in ngOnInit() when user logs in then my guess is that on logout your component get killed, so you can just implement OnDestroy as well and kill subscription there, something like this:
// in my component
ngOnInit() {
this.subscription = this.af.database.list('/tasks')
.subscribe(tasks => this.tasks = tasks);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With