首页 文章

使用userId的Angular firestore app查询无法正常工作

提问于
浏览
1

我有一个带有firebase应用程序的角度6我有一个带有observable的服务(我后来希望多个订阅者监听这个相同的observable)以及一个订阅这个observable的组件我想要实现的是获取auth对象,得到来自它的userId(UID)并在db中搜索具有此id的所有文档

组件在ngOnInit钩子中调用observable,但在阶段它仍然为null,所以我得到了

无法读取undefined的属性'subscribe'

问题是,如果我运行代码来填充订阅块内的observable(获取auth数据)我不会看到数据,如果它在它之外(使用静态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调用一样

更新,如果我初始化这样的服务

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 回答

  • 1

    问题是 expenses$ Observable只有在 auth.user$ 发出一些东西之后才会被定义,因为那时它就被分配了 .

    Solution 1 您可以尝试在更高级别组件的构造函数中注入 ExpenseService 服务,甚至可能 AppComponent ,以便调用 ExpenseService 的构造函数并分配 expenses$ Observable(您只需要注入它,无需任何方法调用或属性访问权限) ) . 此时,在加载组件时,应定义Observable

    Solution 2 使用 of 手动创建Observable expenses$ ,然后订阅 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);
                })
            }
        )
    }
    

相关问题