Angular / Typescript / Firestore - Как да върнете наблюдавана стойност в оператор if

Използвам 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;
    }
}

person Community    schedule 12.01.2018    source източник


Отговори (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)
person Theophilus Omoregbee    schedule 12.01.2018
comment
Това е перфектно. Благодаря ви много за бързия отговор. Наистина добра информация за някой нов в това. Ще маркирам това като отговор след 2 минути. - person ; 12.01.2018
comment
Благодаря за актуализацията Тео. Хубаво е да получите отговор, когато някой предоставя истинска образователна стойност на въпроса с ресурси и код. Много благодарен. - person ; 12.01.2018

Наблюдаемите могат да бъдат асинхронни; те обикновено се използват за тази цел. Кодът извън абонамента в такива случаи се изпълнява преди едно вътрешно абониране.

Ето защо изглежда, че "не актуализира" променливите. Така е, но нямате достъп до тях в правилния момент. Работи, когато твърдо кодирате стойностите, защото тогава абонирането се изпълнява синхронно.

person Lazar Ljubenović    schedule 12.01.2018
comment
Благодаря Лазар. Оценявам отговора. Горният отговор на Тео е отговорът и съвпада с това, което казвате. Благодаря отново. - person ; 12.01.2018
comment
Виждайки, че не сте в SO: няма нужда да благодарите лично в коментарите. Гласуването за и/или приемането на отговор обикновено е правилният начин. Радвам се, че намерихте решението! - person Lazar Ljubenović; 12.01.2018