Frage Abmeldeberechtigungsfehler im Zusammenhang mit abonnierten Observablen


Ich habe eine Komponente, bei der ich eine Observable abonniert habe, um Daten aus Firebase zu ziehen. Der relevante Abonnementcode sieht ungefähr so ​​aus:

[Hinweis: Aktualisierter / korrigierter Code unten.]

// in my component
ngOnInit() {
  // this.af is an injected AngularFire2 instance
  this.tasks = this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

Der Benutzer muss authentifiziert sein, um diese Komponente anzeigen zu können, und ich habe einen Routenschutz installiert, der dies gewährleistet.

Wenn ich mich abmelde, bekomme ich diesen Fehler:

Der Client hat keine Berechtigung, auf die gewünschten Daten zuzugreifen

Ich melde mich mit etwas wie:

// this.auth is an injected FirebaseAuth instance
this.auth.logout();
this.router.navigate(['/login']);

Der Fehler tritt vor dem Router auf navigate Methode wird aufgerufen. Das Problem ist, dass ich dieses aktive Tasks-Beobachter-Abonnement mit einer offenen Web-Socket-Verbindung habe, die gleich nach der logout Methode wird aufgerufen, weil der Benutzer nicht mehr authentifiziert ist.

Das Aufgabenabonnement und die Abmeldefunktion befinden sich in verschiedenen Teilen meiner App. Wenn sie an der gleichen Stelle wären, könnte ich die unsubscribe Methode auf dem Abonnement, wenn ich mich abmelde. Aber trotzdem scheint es unordentlich zu sein, diese Subskriptionslöschungslogik bei mir anzubringen logout Methode. Ich bin mir nicht sicher, wie ich damit umgehen soll.

Wie gehe ich mit der Kündigung des Abonnements für den Beobachter bei der Abmeldung um?

Aktualisierter Code nach Alexander Leonovs Kommentar über doppelte Zuweisung

Alexander wies darauf hin, dass ich der this.tasks Eigenschaft zweimal. Guter Punkt! Dieser Code war falsch. Ich habe das Abonnement keiner Immobilie zugewiesen. Der Code sollte so aussehen:

ngOnInit() {
  // this.af is an injected AngularFire2 instance
  this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

Danke, dass du darauf hingewiesen hast, Alexander.

Lösung: Was ich getan habe

Ich konnte dies teilweise mit Alexander Leonovs Kommentar zum Abbestellen lösen ngOnDestroy in meiner Komponente.

Mit seinem Code in meiner Aufgabenkomponente:

ngOnInit() {
  this.subscription = this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}

Der andere Teil der Lösung beinhaltete das Abonnieren der AngularFire-Authentifizierung, die in meiner Top-Level-Komponente, der AppComponent, beobachtbar ist. Wenn authentifiziert, wird es auf eine Route umgeleitet; Wenn nicht, wird auf eine andere Route umgeleitet:

this.authService.auth$.subscribe((currentUser) => {
  if (currentUser) {
    this.router.navigate(['/tasks']);
  } else {
    this.router.navigate(['/login']);
  }
});

Beim Abmelden wird dieses Abonnement benachrichtigt und der Benutzer wird zur Anmelde-Route umgeleitet. Diese Abfolge von Ereignissen führt zur Auslösung der ngOnDestroy Methode auf meiner Komponente, die sich von den Aufgaben AngularFire abmeldet abmeldet.


7
2017-12-01 00:45


Ursprung


Antworten:


Du bist etwas durcheinander. Sie nutzen this.tasks sowohl um ein Abonnement zu halten:

this.tasks = this.af.database.list(...)

und später als Aufgabenspeicher:

subscribe(tasks => this.tasks = tasks)

Sie müssen eine Seite der Kraft wählen. :)

Um Ihre Frage zu beantworten, benötigen Sie ein wenig mehr Informationen darüber, wie Ihre Anwendung funktioniert. Wenn Sie die Verbindung in ngOnInit () initialisieren, wenn sich der Benutzer anmeldet, dann ist meine Vermutung, dass Ihre Komponente bei der Abmeldung getötet wird. Sie können OnDestroy also einfach implementieren und das Abonnement dort beenden, etwa so:

// in my component
ngOnInit() {
  this.subscription = this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

ngOnDestroy() {
    this.subscription.unsubscribe();
}

6
2017-12-01 03:57