我有一个带有firebase应用程序的Angular 6 我有一个具有可观察性的服务(我稍后希望多个订阅者收听此可观察性) 以及订阅此可观察对象的组件 我试图实现的目的是获取auth对象,从中获取userId(UID),然后在数据库中搜索具有该ID的所有文档
该组件在ngOnInit钩子处调用observable,但是在该阶段它仍然为null,所以我得到
无法读取未定义的属性“ subscribe”
问题是,如果我运行代码以填充订阅块内部的可观察对象(以获取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)
);
}
答案 0 :(得分:1)
问题在于expenses$
仅在auth.user$
发出某些东西之后才定义,因为那是在它被分配时。
解决方案1
您可以尝试将ExpenseService
服务注入到更高级别组件(甚至是AppComponent
)的构造函数中,以便调用ExpenseService
的构造函数并分配expenses$
Observable (您只需要注入它,而无需任何方法调用或属性访问)。此时,当您加载组件时,应定义Observable
解决方案2
使用expenses$
手动创建Observable 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);
})
}
)
}