【问题标题】:AngularFire Observables / Subscribe - Not Setting Class Variable in Same ScopeAngularFire Observables / Subscribe - 不在同一范围内设置类变量
【发布时间】:2018-02-15 09:18:10
【问题描述】:

我正在使用 Firebase 和 AngularFire2 构建一个 Ionic 应用程序。在 Angularfire2 中,您可以进行身份​​验证,但它是可观察的,并且必须订阅才能获取用户对象。问题是我似乎无法设置this.user = user,因为.subscribe 似乎不在同一范围内。

这是一个例子,我有一个auth.ts 和一个app.component.ts。在我的服务中,我进行身份验证,

auth.ts

export class AuthService {

// user: Observable<firebase.User>;
user: object = {
    displayName: null,
    email: null,
    emailVerified: null,
    photoUrl: null,
    uid: null
};

constructor(private facebook: Facebook,
            private googlePlus: GooglePlus,
            private platform: Platform,
            private afAuth: AngularFireAuth) {

    // this.user = afAuth.authState;
    afAuth.authState.subscribe((user: firebase.User) => {

        if (!user) {
            this.user = null;
            return;
        }
        this.user =  {
            displayName: user.displayName,
            email: user.email,
            emailVerified: user.emailVerified,
            photoUrl: user.photoURL,
            uid: user.uid
        }
    });

}

在我的 app.component.ts 中:

app.component.ts

export class MytApp {

rootPage: any = TabsPage;
signinPage = SigninPage;
@ViewChild('nav') nav: NavController;

userProfile: any = null;

constructor(private platform: Platform, 
            private menuCtrl: MenuController,
            private statusBar: StatusBar, 
            private splashScreen: SplashScreen,
            private authService: AuthService) {

    // this.authService.user.subscribe((user: firebase.User) => {
        // var user = authService.user;
        // if (user) {
        //  this.userProfile = user;
        //  this.onLoad(TabsPage);
        // } else {
        //  this.userProfile = null;
        //  this.onLoad(SigninPage);
        // }
    // });

    platform.ready().then(() => {
        // Okay, so the platform is ready and our plugins are available.
        // Here you can do any higher level native things you might need.
        statusBar.styleDefault();
        splashScreen.hide();

        var user = authService.user; /* HERE */
        console.log(user);
        if (user) {
            this.userProfile = user;
            this.onLoad(TabsPage);
        } else {
            this.userProfile = null;
            this.onLoad(SigninPage);
        }
    });
}

}

如您所见,在var user = authService.user; 之后,我运行console.log(user);,得到的是:

console.log(user);

   displayName: null,
   email: null,
   emailVerified: null,
   photoUrl: null,
   uid: null

我在 Firebase 中使用用户对象来定位用户数据,所以这是必要的。问题是用户对象没有更新,就像它超出了afAuth.authState.subscribe((user: firebase.User) =&gt; {} 的“范围”。

知道我怎么不能订阅,只是简单地获取用户对象,或者可能从订阅中提取数据,以便我可以轻松地从其他组件中检索它(因为它是一项服务)?请帮忙!

【问题讨论】:

    标签: angular firebase ionic-framework rxjs angularfire2


    【解决方案1】:

    您不能在服务中使用subscribe()。你想要做的是返回一个Observable,让组件自己处理Observables,而不是在服务中。原因是您的 API 调用是异步的,您的组件无法等待 http 调用的解析。

    您可以做的是通过将AngularFireAuth 映射到您想要的对象来返回一个 Observable。

    export class AuthService {
        public user: Observable<any>; //this can be any type you wish
        constructor(private facebook: Facebook,
                    private googlePlus: GooglePlus,
                    private platform: Platform,
                    private afAuth: AngularFireAuth) {
    
            this.user =
                afAuth.authState.map((user: firebase.User) => {
                    if (!user) {
                        return null;
                    }
                    else return {
                        displayName: user.displayName,
                        email: user.email,
                        emailVerified: user.emailVerified,
                        photoUrl: user.photoURL,
                        uid: user.uid
                    }
                });
        }
    }
    

    现在,您可以在任何其他组件中订阅您的AuthService.user

    export class MytApp {
    
        rootPage: any = TabsPage;
        signinPage = SigninPage;
        @ViewChild('nav') nav: NavController;
    
        userProfile: any = null;
    
        constructor(private platform: Platform,
                    private menuCtrl: MenuController,
                    private statusBar: StatusBar,
                    private splashScreen: SplashScreen,
                    private authService: AuthService) {
    
    
            platform.ready().then(() => {
                // Okay, so the platform is ready and our plugins are available.
                // Here you can do any higher level native things you might need.
                statusBar.styleDefault();
                splashScreen.hide();
                //subscribe to AuthService
                authService.subscribe(user => {
                    console.log(user);
                    if (user) {
                        this.userProfile = user;
                        this.onLoad(TabsPage);
                    } else {
                        this.userProfile = null;
                        this.onLoad(SigninPage);
                    }
                })
            });
        }
    }
    

    【讨论】:

    • 您好,感谢您的回复!这是否意味着如果我想使用uid,我必须将我的每一个firebase函数都放在用户订阅中?那么,例如调用db.list(this.user.uid + '/Lists/'); 的“addNewList()”或“deleteList()”之类的?
    • @Kenny 在技术上是的,但是如果你将firebase 函数包装到服务中,比如FireBaseListService,那么你可以做的就是将AuthService 注入到FireBaseListSerivce 中。然后,您可以使用switchMap。这使您无需订阅服务,同样,您可以将您的Observables 传递给组件进行处理。
    猜你喜欢
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    • 2016-04-30
    • 1970-01-01
    相关资源
    最近更新 更多