我的用户可以喜欢英雄列表,所以我的firebase规则/数据中有这个结构:
"user_flags": {
"$uid": {
".write": "auth.uid == $uid",
".read": "auth.uid == $uid",
"liked": {
"$heroIdx": {
".validate": "newData.isString()"
}
}
}
}
在我的代码中,我想订阅“喜欢的英雄”参考,这就是我的所作所为:
import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import { AngularFireAuth } from 'angularfire2/auth';
@Injectable()
export class UserFlagsService {
likedHeroes$: Observable<string[]>;
constructor(
private afAuth: AngularFireAuth,
private db: AngularFireDatabase
) {
this.likedHeroes$ = afAuth.authState.flatMap(user => {
return user && user.uid
? this.db.list(`user_flags/${user.uid}/liked`)
.map(heroes => heroes.map(hero => <string>hero.$value))
: Observable.of([])
});
}
}
一切正常,直到用户退出...即使检查user
和user.uid
,查询user_flags/MY_ID_HERE/liked
似乎也会被触发,我会收到“权限被拒绝”。
我尝试使用订阅并注意注销以取消订阅,但它也无效...查询仍然被触发并因“权限被拒绝”而失败
我应该如何处理?我希望我的服务返回一个可靠的observable,以便我可以在我的组件中订阅它。
非常感谢你的帮助
答案 0 :(得分:3)
我假设您要确保在退出时您在视图中呈现的数据会消失吗?
如果是这种情况,我建议使用switchMap operator from RXJS和以下模式:
this.userProvider = this.afAuth.authState;
this.likedHeroes$ = this.userProvider.switchMap((auth) => {
if(auth){
return this.af.list('user_flags/' + auth.uid + '/liked');
}
});
您需要添加以下内容以导入switchMap运算符:
import 'rxjs/add/operator/switchMap';
如果您希望我更多地填写此内容,或者如果我对您尝试实现的目标的假设不正确,请给我一些评论。我一直在努力找出做这些事情的最好方法。
您还应该从Angular Firebase YouTube查看this video,它可能会帮助您解决问题中的一些问题。
答案 1 :(得分:1)
我设法通过创建一个BehaviorSubject并在&#34;注销&#34;之前取消订阅事件来使其工作。被触发了。 这是我的提供者:
import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/Subscription';
import { UserProvider } from '../../providers/user/user';
@Injectable()
export class UserFlagsProvider {
likedHeroes$: Observable<string[]>;
subHeroesLiked: Subscription;
constructor(
protected userProvider: UserProvider,
protected db: AngularFireDatabase
) {
const heroesLikedSubject: BehaviorSubject<string[]> = new BehaviorSubject([]);
this.likedHeroes$ = heroesLikedSubject.asObservable();
this.userProvider.user$.subscribe(user => {
if (user) {
this.subHeroesLiked = this.db.list(`user_flags/${user.uid}/liked`).subscribe(heroesSlugs => {
heroesLikedSubject.next(heroesSlugs.map(hero => <string>hero.$key));
});
}
});
this.userProvider.signingOut$.subscribe(() => {
this.subHeroesLiked.unsubscribe();
});
}
}
我的userProvider
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { AngularFireAuth } from 'angularfire2/auth';
@Injectable()
export class UserProvider {
user$: Observable<firebase.User>;
user: firebase.User;
signingOut$: Subject<any> = new Subject();
constructor(private afAuth: AngularFireAuth) {
this.user$ = afAuth.authState;
this.user$.subscribe(user => this.user = user);
}
// [...]
signout() {
this.signingOut$.next();
return this.afAuth.auth.signOut();
}
}
希望它有所帮助。
仅供参考,由于未知原因,这对angularfire2-offline
无效(现在)。
如果有人看到更好的方法,我感兴趣