我正在使用Ionic2
与Angularfire2
访问Firebase Authentication
。
我访问以下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;
});
}
此外,在Firebase身份验证中,我有以下实时数据库规则:
"rules": {
".read": "auth != null",
".write": "auth != null",
}
问题
这在用户登录时完美无缺(即auth != null
),但是一旦用户退出,auth == null
,我就会收到以下错误:
错误错误:未捕获(在承诺中):错误:在/ chat处的permission_denied: 客户无权访问所需数据。错误: permission_denied at / chat:客户没有访问权限 想要的数据。
问题
正如您在上面的代码中看到的那样,我尝试从Firebase身份验证服务unsubscribe
,但必须正确执行此操作。如果有人可以建议我应该unsubscribe
如何停止我的应用程序查询Firebase数据库,我将非常感谢您的帮助。
答案 0 :(得分: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
来获取数据。如果用户注销,则auth状态将更改为null,因此UI数据将更改为空列表。即使用户没有注销,他仍然无法看到数据。
更新:
重构其他答案:
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
。
答案 1 :(得分: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
的正确方法。