AngularFire Observables / Subscribe - Not Setting Class Variable in Same Scope

偶尔善良 提交于 2019-12-12 04:38:18

问题


I'm building an Ionic app using Firebase, and therefore AngularFire2. In Angularfire2 you can authenticate, but it's an observable and have to subscribe to get the user object. The problem is that I can't seem to set this.user = user because it doesn't seem like .subscribe is in the same scope.

Here's an example, I have a auth.ts and an app.component.ts. In my service, I authenticate,

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
        }
    });

}

and in my 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);
        }
    });
}

}

As you can see, right after var user = authService.user; I run console.log(user); and what I get is:

console.log(user);

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

I use the user object for targeting user data in Firebase, so it's necessary. The problem is that the user object isn't updated, it's like it's out of the "scope" of the afAuth.authState.subscribe((user: firebase.User) => {}.

Any idea how I can not subscribe, and just simply get the user object, or maybe extract the data from the subscribe so that I can easily retrieve it (because it's a service) from other components? Please help!


回答1:


You can't do a subscribe() in your service. What you want to do, is to return an Observable, and let the components handle the Observables themselves, and not in the service. Reason for this is because your API call is asynchronous and your components cannot wait for the resolve of the http calls.

What you can do is you can return an Observable by mapping your AngularFireAuth to an object that you desire.

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
                }
            });
    }
}

Now, you can subscribe to your AuthService.user in any other component:

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);
                }
            })
        });
    }
}


来源:https://stackoverflow.com/questions/46082722/angularfire-observables-subscribe-not-setting-class-variable-in-same-scope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!