【问题标题】:Angular / Typescript / Firestore - How to return an observable value within an if statementAngular / Typescript / Firestore - 如何在 if 语句中返回可观察值
【发布时间】:2018-06-21 18:15:00
【问题描述】:

我正在使用 Angular 和 Firestore。我正在检查 firestore 以获取我的路由守卫内的值。

我发现在页面刷新时,它返回为未定义。但是,如果我只是硬编码返回 true 或 false,它就可以工作。

我的 if 语句中的任何日志总是正确返回,但由于某种原因似乎没有更新我的全局变量。

如果我使用我的站点导航返回到根目录并浏览我的站点,它可以正常工作。但是,当我刷新页面时,它返回为未定义。

这可能是范围界定问题吗?

路线守卫

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';

import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Subscription } from 'rxjs/Subscription';


//testing
import { Observable } from 'rxjs/Observable';
import { AngularFireAuth } from 'angularfire2/auth';

@Injectable()
export class CheckBillingService implements CanActivate {
    private _subscription: Subscription;
    private userBillingDocRef: AngularFirestoreDocument<any>;
    userBilling: Observable<any>;
    public activeAccount:Observable<boolean>

    constructor(private authService: AuthService,
                private router: Router,
                private auth: AngularFireAuth,
                private readonly afs: AngularFirestore) {}

    canActivate(): Observable<boolean> {
        this.authService.user.subscribe((user) => {
            if (user) {
                var userId = user.uid;

                this.userBillingDocRef = this.afs.doc('user_billing/${userId}');

                this.userBilling = this.userBillingDocRef.snapshotChanges();
                this.userBilling.subscribe((value) => {

                    const data = value.payload.data();

                    if (data.account_status == "Active") {
                        this.activeAccount = Observable.of(true);
                        console.log('inside if statement for active = ', this.activeAccount);
                    } else {
                        this.activeAccount = Observable.of(false);
                        console.log('inside if statement for not active = ', this.activeAccount);
                        this.router.navigate(['resubscribe']);
                        return Observable.of(false);
                    }

                    console.log('userBilling.subscribe = ', this.activeAccount);
                });

                console.log('just outside userBilling.subscribe = ', this.activeAccount);
            }
        });

        // When refreshig my page, this returns as undefined.
        // If I navigate to the correct page and work my way through the site it works fine
        // However, refresh returns undefined.

        console.log('out of auth = ', this.activeAccount);

        return this.activeAccount;
    }
}

【问题讨论】:

    标签: javascript angular typescript google-cloud-firestore scoping


    【解决方案1】:

    Observables 可以是异步的;它们通常用于此目的。在这种情况下,订阅之外的代码会在内部订阅之前执行。

    这就是为什么它看起来像是“不更新”变量的原因。是的,但是您没有在正确的时间访问它们。当您对值进行硬编码时它会起作用,因为订阅是同步执行的。

    【讨论】:

    • 谢谢拉扎尔。我很感激你的回应。 Theo 的上述回复就是答案,与您所说的相符。再次感谢。
    • 看到你不在 SO:无需亲自在 cmets 中感谢。赞成和/或接受答案通常是要走的路。很高兴您找到了解决方案!
    【解决方案2】:

    根据您的代码,页面将在您的可观察方法返回之前运行,因为它是异步运行的,而不是像这样返回完整的可观察方法

     canActivate(): Observable<boolean> {
    
        return Observable.create(observer=> {
    this.authService.user.subscribe((user) => {
    
                    if (user) {
    
                        var userId = user.uid;
    
                        this.userBillingDocRef = this.afs.doc('user_billing/${userId}');
    
                        this.userBilling = this.userBillingDocRef.snapshotChanges();
                        this.userBilling.subscribe((value) => {
    
                            const data = value.payload.data();
    
                            if (data.account_status == "Active") {
                                this.activeAccount = Observable.of(true);
     // observe here 
            observer.next(true)
                                console.log('inside if statement for active = ', this.activeAccount);
                            } else {
                                this.activeAccount = Observable.of(false);
              // observe here 
            observer.next(false)
                                console.log('inside if statement for not active = ', this.activeAccount);
                                this.router.navigate(['resubscribe']);
                            }
    
                            console.log('userBilling.subscribe = ', this.activeAccount);
                        });
    
                        console.log('just outside userBilling.subscribe = ', this.activeAccount);
    
                    }
    
                });
        });
    
    
                // When refreshig my page, this returns as undefined.
                // If I navigate to the correct page and work my way through the site it works fine
                // However, refresh returns undefined.
    
                console.log('out of auth = ', this.activeAccount);
    
            }
    

    注意我在Observer.create 中包装了所有内容的位置,您可以在此处了解更多信息https://stackoverflow.com/a/44334611/5836034

    然后observer.next 将返回您真正希望canActivate 挂钩做出反应的内容

      // observe here 
            observer.next(true)
        observer.next(false)
    

    【讨论】:

    • 这是完美的。非常感谢您的快速回复。对于刚接触这个的人来说,这是非常好的信息。我会在 2 分钟内将此标记为答案。
    • 感谢西奥的更新。如果有人通过资源和代码为问题提供了一些真正的教育价值,很高兴得到回应。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-18
    • 2018-04-11
    • 1970-01-01
    • 2020-06-24
    相关资源
    最近更新 更多