如何在 ngrx/effects 中使用承诺

How to use a promise in ngrx/effects

我在 Angular.

中使用带有 Firebase 身份验证的@ngrx/store 和@ngrx/effects

这是构造函数:

constructor(
        private actions: Actions,
        private afAuth: AngularFireAuth,
        private db: AngularFirestore,
        private router: Router
    ) {}

效果是这样的:

@Effect()
    getUser: Observable<Action> = this.actions
        .ofType(authActions.GET_USER)
        .map((action: authActions.GetUser) => action.payload)
        .switchMap(payload => this.afAuth.authState)
        .map(authData => {
            if (authData) {
                const user = new User(
                    authData.uid,
                    authData.displayName,
                    authData.email,
                    authData.photoURL
                );

                return new authActions.Authenticated(user);
            } else {
                return new authActions.NotAuthenticated();
            }
        })
        .catch(err => Observable.of(new authActions.AuthError()));

此代码按预期工作,但我需要存储在 Firestore 文档中的其他值,我可以通过这种方式检索它们:

[...]
if (authData) {
    const userRef = this.db.firestore
        .collection('users')
        .doc(authData.uid)
        .get()
        .then(doc => {
            const userData = doc.data();
                return {
                    uid: userData.uid,
                    displayName: userData.displayName,
                    email: userData.email,
                    photoURL: userData.photoURL,
                    role: userData.roles
                };
            });
[...]

但是因为这是一个承诺,所以我不能在我使用 user 的地方使用 userRef。 这个问题有解决办法吗?

只需要将 switchMap 上移一个级别即可。

@Effect()
getUser: Observable<Action> = this.actions
    .ofType(authActions.GET_USER)
    .map((action: authActions.GetUser) => action.payload)
    .switchMap(payload =>
        this.afAuth.authState.switchMap(auth => {
            if (auth) {
                return this.db.doc<User>(`users/${auth.uid}`).valueChanges();
            } else {
                return Observable.of(null);
            }
        })
    )
    .map(authData => {
        if (authData) {
            const user = new User(
                authData.uid,
                authData.displayName,
                authData.email,
                authData.photoURL,
                authData.roles
            );

            return new authActions.Authenticated(user);
        } else {
            return new authActions.NotAuthenticated();
        }
    })
    .catch(err => Observable.of(new authActions.AuthError()));