Firebase如何取消订阅
我使用Ionic2
与Angularfire2
访问Firebase Authentication
。Firebase如何取消订阅
我访问以下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
,我将不胜感激。
这不是问题的确切答案,但我的观点是,如果我们以其他方式这样做,我们将永远不会遇到这个问题。
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
内的服务。
该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
的正确方法。
你为什么不''this.firelist.unsubscribe()' – Skeptor
嗨Skeptor,感谢您的反馈。 'this.firelist'是一个'rxjs/Observable',并且api没有'unsubscribe'功能。但是,它返回一个'订阅',确实有一个,所以这是我没有成功地尝试,如上所示。 http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html –
Richard
我从不取消订阅,所以不确定语法。但在我看来,你需要为每个http调用观看auth对象状态,而不是取消订阅。我将提供一种不同的方式来编写相同的代码,以及我在应用程序中的做法。 (我使用aws,但它们几乎相同) – Skeptor