3

我使用Ionic2Angularfire2訪問Firebase AuthenticationFirebase如何取消訂閱

我訪問以下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; 
    }); 
} 

另外,在火力地堡認證,我有以下實時數據庫規則:

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

問題

這工作完全在用戶已登錄(即auth != null),但只要用戶註銷,並auth == null,我收到以下錯誤:

ERROR Error: Uncaught (in promise): Error: permission_denied at /chat: Client doesn't have permission to access the desired data. Error: permission_denied at /chat: Client doesn't have permission to access the desired data.

問題

正如你可以在上面的代碼中看到,我嘗試unsubscribe從Firebase身份驗證服務,但必須做到不正確。如果有人可以建議我應該如何阻止我的應用查詢Firebase數據庫unsubscribe,我將不勝感激。

+0

你爲什麼不''this.firelist.unsubscribe()' – Skeptor

+0

嗨Skeptor,感謝您的反饋。 'this.firelist'是一個'rxjs/Observable ',並且api沒有'unsubscribe'功能。但是,它返回一個'訂閱',確實有一個,所以這是我沒有成功地嘗試,如上所示。 http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html – Richard

+0

我從不取消訂閱,所以不確定語法。但在我看來,你需要爲每個http調用觀看auth對象狀態,而不是取消訂閱。我將提供一種不同的方式來編寫相同的代碼,以及我在應用程序中的做法。 (我使用aws,但它們幾乎相同) – Skeptor

回答

1

這不是問題的確切答案,但我的觀點是,如果我們以其他方式這樣做,我們將永遠不會遇到這個問題。

P.S:我從來沒有使用firebase,我使用AWS,因此firebase代碼可能不準確,我們將討論它。

這裏是我的版本:

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 
       ) 
      ) 
     ) 
    ); 
} 

驗證服務

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); 
     } 
    }); 

}  

的代碼非常原始,但我希望它傳達的理念。在這裏我正在觀察用戶身份驗證狀態並執行flatMap來獲取數據。如果用戶註銷,則認證狀態更改爲空,因此在UI中數據更改爲空列表。即使用戶沒有註銷,他仍然無法看到數據。


UPDATE

重構對方回答:

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)) 
     ] 
    ); 
} 

除非你正在使用Subject緩存響應從不使用subscribe內的服務。

0

unsubscribe工作正常。這個問題原來,下面的函數我用過,導致它由於某種原因,訂閱兩次:

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); 
      }); 
     }); 
    }); 
} 

出於某種原因,第3行以上的被稱爲兩次(即使該功能只調用一次)。這是創建第二個subscription,而第一個subscription從來沒有unsubscribed

因此看起來Observable的創建不正確。我不確定是什麼,但創建Observable的正確方法。

+0

我發佈了一個關於如何創建'Observable'的問題,以便這裏只有一個訂閱: https://stackoverflow.com/questions/44883886/observable-create-is-called-twice – Richard

+0

你不應該使用'Observable.create'。在使用map進行一些轉換之後直接返回'this.firebaseDataService'。 – Skeptor

+0

我不知道該怎麼做,因爲使用'Observable'的列表當前正在訂閱它,即它需要動態更新。 – Richard