Угловые запросы приложения firestore с userId не работают - PullRequest
0 голосов
/ 09 ноября 2018

У меня угловой 6 с применением пожарной базы У меня есть служба с наблюдаемой (позже я хочу, чтобы несколько подписчиков слушали эту же наблюдаемую) а также компонент, который подписывается на эту наблюдаемую то, что я пытаюсь достичь, это получить объект auth, получить из него userId (UID) и найти в БД все документы с этим id

компонент вызывает наблюдаемое на хуке ngOnInit, но на этапе он все еще нулевой, поэтому я получаю

Невозможно прочитать свойство 'подписка' из неопределенного

проблема в том, что если я запускаю код, чтобы заполнить наблюдаемое внутри блока подписки (чтобы получить данные аутентификации), которое я не получаю, чтобы увидеть данные, если они находятся вне их (выполняется синхронизация с использованием статического UID), чем они действительно заполняется правильно и показывает данные вот код услуги

import { Injectable, EventEmitter } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, DocumentChangeAction } from '@angular/fire/firestore';
import { Expense } from '../model/Expense';
import { Observable, ReplaySubject, Subject, from } from 'rxjs';
import { map } from 'rxjs/operators';
import { AuthService } from '../core/services/auth.service';

@Injectable({
    providedIn: 'root',
})
export class ExpenseService {

    private dbPath = '/expenses';

    expenseDetailEvent: EventEmitter<Expense> = new EventEmitter<Expense>();

    expensesRef: AngularFirestoreCollection<Expense> = null;
    expenses$: Observable<Expense[]>;

    constructor(private db: AngularFirestore, auth: AuthService) {
        auth.user$.subscribe(
            user => {
                this.expensesRef = this.db.collection<Expense>(this.dbPath, ref =>
                    ref.where('clientId', '==', user.uid)
                );
                this.expenses$ = this.expensesRef.snapshotChanges().pipe(
                    map(actions =>
                        actions.map(a => {
                            const data = a.payload.doc.data() as Expense;
                            const id = a.payload.doc.id;
                            return { id, ...data };
                        })
                    )
                );
            },
            error => console.log(error)
        );
    }

    createExpense(expense: Expense): Observable<any> {
        return from(this.expensesRef.add(expense));
    }

    updateExpense(expense: Expense): Observable<any> {
        return from(this.expensesRef.doc(expense.id).update(expense));
    }
}

и компонент просто делает

ngOnInit() {
        this.expenseService.expenses$.subscribe(expenses => this.expenses = expenses);
    }

Я заметил, что все примеры в сети, вызывают это на компоненте, но я чувствую, что вызов базы данных должен быть в службе аналогично тому, как это делается с обычными вызовами HTTP API

UPDATE если я инициализирую службу, как это

expenses$: Observable<Expense[]> = of([]);

так что, конечно, приложение не падает, но я не вижу никаких данных если я просто вытаскиваю код наружу и использую статический UID, чем он делает ... (конечно, user.uid - это то же самое, что и статическая строка, которую я вставил)

вот обновленный код

constructor(private db: AngularFirestore, auth: AuthService) {
    console.log('being here ,i see the data on screen using the static uid');
    this.expensesRef = this.db.collection<Expense>(this.dbPath, ref =>
        ref.where('clientId', '==', 'noYVScDtKfNB5aFqRkAJR7ghxio2')
    );
    this.expenses$ = this.expensesRef.snapshotChanges().pipe(
        map(actions =>
            actions.map(a => {
                const data = a.payload.doc.data() as Expense;
                const id = a.payload.doc.id;
                return { id, ...data };
            })
        )
    );
    auth.user$.subscribe(
        user => {
            console.log('if inside here than it will not show any data on screen');

        },
        error => console.log(error)
    );
}

1 Ответ

0 голосов
/ 09 ноября 2018

Проблема в том, что наблюдаемая expenses$ будет определена только после того, как auth.user$ что-то испустит, потому что тогда наступит момент, когда она будет назначена.

Раствор 1 Вы можете попробовать внедрить службу ExpenseService в конструктор компонента более высокого уровня, может быть, даже AppComponent, чтобы вызвать конструктор ExpenseService и присвоить expenses$ Observable (вам просто нужно внедрить его, без какого-либо вызова метода или доступа к свойству). В этот момент к моменту загрузки компонента должно быть определено наблюдаемое

Решение 2 Вручную создайте Observable expenses$, используя of, а затем подписавшись на this.expensesRef.snapshotChanges(), вы можете отправить значения обратно в expenses$

Что-то вроде:

...

expensesSubject = new Subject<Expense[]>();
expenses$: from(expensesSubject);

constructor(private db: AngularFirestore, auth: AuthService) {
    auth.user$.subscribe(
        user => {
            this.expensesRef = this.db.collection<Expense>(this.dbPath, ref =>
                ref.where('clientId', '==', user.uid)
            );
            this.expensesRef.snapshotChanges().pipe(
                map(actions =>
                    actions.map(a => {
                        const data = a.payload.doc.data() as Expense;
                        const id = a.payload.doc.id;
                        return { id, ...data };
                    })
                )
            ).subscribe((whatever) => {
              expensesSubject.next(whatever);
            })
        }
    )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...