Firebase how to unsubscribe

I am using Ionic2

c Angularfire2

to access Firebase Authentication

.

I am accessing the following rxjs/Observable

:

chats.ts

  this.firelist = this.dataService.findChats();
  this.subscription = this.firelist.subscribe(chatItems => {
     ...
  });

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

      

dataService.ts

findChats(): Observable<any[]> {
        this.firebaseDataService.findChats().forEach(firebaseItems => {
           ...
           observer.next(mergedItems);
        });
}

      

firebaseDataService.ts

findChats(): Observable<any[]> { // populates the firelist
    return this.af.database.list('/chat/', {
        query: {
            orderByChild: 'negativtimestamp'
        }
    }).map(items => {
        const filtered = items.filter(
            item => (item.memberId1 === this.me.uid || item.memberId2 === this.me.uid)
        );
        return filtered;
    });
}

      

Also, in Firebase Authentication I have the following realtime database rules:

  "rules": {
      ".read": "auth != null",
      ".write": "auth != null",
  }

      

Problem

This works fine when the user is logged in (i.e. auth != null

), but as soon as the user is logged out as well auth == null

, I get the following error:

ERROR error: impurity (in the promise): error: allowed in / chat: The client does not have access to the requested data. Error: permission_denied at / chat: The client does not have permission to access the required data.

Question

As you can see in the above code, I am trying to execute unsubscribe

from the Firebase Authentication Service, but you must be doing it wrong. If anyone can advise on how I should be able unsubscribe

to stop the application querying the Firebase database, I would appreciate some help.

+3


source to share


2 answers


This is not an accurate answer to the question, but my argument is that we will never get to this problem if we do it differently.

PS: I have never used firebase, I am using AWS, so the firebase code may not be accurate, we are discussing it.

Here's my version:

findChats(): Observable<any[]> { // populates the firelist
    return 
      this.authService.getCurrentUser()
        .flatMap(user => user === null ? 
          Observable.empty():        
          this.af.database.list('/chat/', {
             query: {
                orderByChild: 'negativtimestamp'
             }
           })
          .map(items => 
             return items.filter(
               item => (
                  item.memberId1 === this.me.uid || 
                  item.memberId2 === this.me.uid
               )
             ) 
          )
     );
}

      

Auth Service

public currentUser = new BehaviorSubject(null);

constructor(){

    firebase.auth().onAuthStateChanged(function(user) {
        if (user) {
           // User is signed in.
           currentUser.next(user);
        } else {
         // No user is signed in.
           currentUser.next(null);
        }
    });

}    

      



The code is very crude, but I hope it conveys the idea. Here I am observing user authentication status and doing flatMap

to fetch data. If the user logs out, the authentication state goes to zero, so the result of changing the UI data to an empty list. Even if the user is not logged out, they still cannot see the data.


UPDATE :

Refactoring another answer:

findChats(){
   return Observable.merge(
       this.firebaseDataService
           .findChats()
           .flatMap(chats => Observable.from(chats)),
       this.localDataService
           .findChats()
           .flatMap(chats => Observable.from(chats))
   )
   .filter(chat => !!chat)
   .toArray()
   .map(chats => [
      ...chats.sort(
        (a, b) => 
           parseFloat(a.negativtimestamp) - parseFloat(b.negativtimestamp))
      ]
   );  
}

      

Except when you are doing caching with Subject

never use subscribe

inside a service.

+1


source


unsubscribe

works correctly. The problem is that the following function that I have used causes it to be signed twice for some reason:

findChats(): Observable<any[]> {
    return Observable.create((observer) => {
        this.chatSubscription2 = this.firebaseDataService.findChats().subscribe(firebaseItems => {
            this.localDataService.findChats().then((localItems: any[]) => {
                let mergedItems: any[] = [];
                if (localItems && localItems != null && firebaseItems && firebaseItems != null) {
                    for (let i: number = 0; i < localItems.length; i++) {
                        if (localItems[i] === null) {
                            localItems.splice(i, 1);
                        }
                    }
                    mergedItems = this.arrayUnique(firebaseItems.concat(localItems), true);
                } else if (firebaseItems && firebaseItems != null) {
                    mergedItems = firebaseItems;
                } else if (localItems && localItems != null) {
                    mergedItems = localItems;
                }
                mergedItems.sort((a, b) => {
                    return parseFloat(a.negativtimestamp) - parseFloat(b.negativtimestamp);
                });
                observer.next(mergedItems);
                this.checkChats(firebaseItems, localItems);
            });
        });
    });
}

      



For some reason, the 3rd line above is called twice (although the function is only called once). This creates the second subscription

and the first subscription

never unsubscribed

.

So it looks like the creation Observable

is wrong. I'm not sure if this is the correct way to create Observable

.

0


source







All Articles