Angularfire2:auth更改和权限被拒绝的嵌套observable

时间:2017-07-24 09:05:46

标签: firebase firebase-realtime-database firebase-authentication observable angularfire2

我的用户可以喜欢英雄列表,所以我的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([])
    });
  }
}

一切正常,直到用户退出...即使检查useruser.uid,查询user_flags/MY_ID_HERE/liked似乎也会被触发,我会收到“权限被拒绝”。

我尝试使用订阅并注意注销以取消订阅,但它也无效...查询仍然被触发并因“权限被拒绝”而失败

我应该如何处理?我希望我的服务返回一个可靠的observable,以便我可以在我的组件中订阅它。

非常感谢你的帮助

2 个答案:

答案 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无效(现在)。

如果有人看到更好的方法,我感兴趣