AngularFire Observables / Subscribe - 不在同一范围内设置类变量

Ken*_*nny 0 rxjs firebase ionic-framework angularfire2 angular

我正在使用 Firebase 构建一个 Ionic 应用程序,因此使用 AngularFire2。在 Angularfire2 中,您可以进行身份​​验证,但它是一个 observable,必须订阅才能获取用户对象。问题是我似乎无法设置,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
        }
    });

}
Run Code Online (Sandbox Code Playgroud)

在我的 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);
        }
    });
}

}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,在var user = authService.user;我跑完之后console.log(user);,我得到的是:

控制台日志(用户);

   displayName: null,
   email: null,
   emailVerified: null,
   photoUrl: null,
   uid: null
Run Code Online (Sandbox Code Playgroud)

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

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

Coz*_*ure 5

你不能做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
                }
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以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);
                }
            })
        });
    }
}
Run Code Online (Sandbox Code Playgroud)