user1738539
user1738539

Reputation: 941

AngularFire2 unsubscribe on logout, database permission errors on unclosed subscription

I have this code here using AngularFire2 version that I use to grab some member from the database on one of my components.

I have an issue when I call this logout in the same component. I unsubscribe from the Subscriptions but I still get the error in the console saying Exception was thrown by user callback. Error: permission_denied at /users/uid. I know it's because I am no longer signed in and my database rules don't allow this read operation. I don't know why it's still trying to read data if I already unsubscribed.

    constructor(private afAuth: AngularFireAuth, private db: AngularFireDatabase) {
        this.user = afAuth.authState;

        this.userSub = this.user.subscribe(auth => {
            if (auth) {
                this.member = db.object('/users/' + auth.uid);
                this.dbSub = this.member.subscribe();
            }
        });
    }

    logout() {
        this.dbSub.unsubscribe();
        this.userSub.unsubscribe();

        this.afAuth.auth.signOut()
            .then(() => this.router.navigateByUrl('/login'));
    }

Upvotes: 4

Views: 2137

Answers (2)

user1689987
user1689987

Reputation: 1546

If you have a logout button on many pages just navigate to a different page and call logout from there. Then you don't have to litter your code with unsubscribes. When you navigate to a different angular page the components and their subscribes will be garbage collected.

Upvotes: 0

Alexander Staroselsky
Alexander Staroselsky

Reputation: 38807

You could perhaps try using an RxJS Subject along with the operator takeUntil() to help ensure the observable is cleaned up prior to the signOut():

import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/takeUntil';

export class Foo {
    private ngUnsubscribe: Subject<void> = new Subject<void>();

    constructor(private afAuth: AngularFireAuth, private db: AngularFireDatabase) {
        this.user = afAuth.authState;

        this.userSub = this.user.subscribe(auth => {
            if (auth) {
                this.member = db.object('/users/' + auth.uid);

                this.dbSub = this.member
                    .takeUntil(ngUnsubscribe)
                    .subscribe(results => console.log(results));
            }
        });
    }

    logout() {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();

        this.userSub.unsubscribe();

        this.afAuth.auth.signOut()
            .then(() => this.router.navigateByUrl('/login'));
    }
}

Upvotes: 6

Related Questions