我的服务中有一个方法,我试图在其中返回一个 User 对象的 Observable。这是我的代码 -
constructor(private firestore: AngularFirestore,
private db: AngularFireDatabase) { }
/**
* get user with given email, if not return null
*
* @param email email to fetch
*/
getUserByEmail(email: string): Observable<User> {
var user: User;
let userRef = this.firestore.collection("users").ref.where('email', '==', email);
userRef.get().then(res => res.forEach(userDoc => {
user = userDoc[0].data() as User; // since email IDs are unique, I want the 0th element.
user.id = userDoc[0].id;
console.log(user); // has the data
// return user; // doesn't work, not the right thing
}));
console.log(user); // undefined, since call is async
return of(user);
}
在组件内部,我想要下一步的数据,所以我这样做了 -
checkEmail() {
var user$: User
this.us.getUserByEmail(this.existingUserForm.value.email).subscribe(user => {
console.log(user);
if (user) {
this.msg$ = "success";
// next steps
}
else {
this.msg$ = "User with this email does not exist!";
}
});
}
我不确定如何从我的服务返回一个可观察对象,以便我可以在我的组件中使用数据。这是做我想做的事情的正确方法吗?
最佳答案
如果您想要从 Firestore 中观察到,您需要在 AngularFirestoreCollection 上返回 .valueChanges()。 阅读此文档以供引用:https://github.com/angular/angularfire2/blob/master/docs/firestore/querying-collections.md .
在您的服务中:(为了清楚起见,我已经声明了 collection 和 user$ 变量)。
getUserByEmail(email: string): Observable<User> {
const collection = this.firestore.collection<User>('users', ref => ref.where('email', '==', email))
const user$ = collection
.valueChanges()
.pipe(
map(users => {
const user = users[0];
console.log(user);
return user;
})
);
return user$;
}
如果您还需要用户的 ID,则需要使用 snapshotChanges()。有时,在保存到 firestore 以避免使用 snapshotChanges 时,维护用户数据的 ID 更容易(在我看来)。
// Query the users by a specific email and return the first User with ID added
return this.firestore.collection<User>('users', ref => ref.where('email',
'==', email))
.snapshotChanges()
.pipe(map(users => {
const user = users[0];
if (user) {
const data = user.payload.doc.data() as User;
const id = user.payload.doc.id;
return { id, ...data };
}
else {
return null;
}
}));
在您的组件代码中,您可以通过以下方式调用它
checkEmail() {
this.user$ = this.us.getUserByEmail('email@gmail.com')
.pipe(
tap(user => {
if (user) {
this.msg = 'success';
} else {
this.msg = 'User with this email does not exist!';
}
}));
}
请注意,在您调用 this.user$ 上的订阅之前,用户将为空,或者在您的 html 中使用处理订阅和取消订阅的异步管道。
<div *ngIf="(user$ | async) as user">{{ user.email }}</div>
尽量避免在您的 html 中对同一个可观察对象多次使用异步管道,而是将其设置为我在上面(作为用户)所做的本地 html 变量,以避免不必要的数据访问 db
关于命名约定的说明。 Observables 的变量名通常以“$”为后缀,而其他(字符串、数字等)则没有“$”。
关于angular - 如何从 Angular 7 中的 Firestore 查询中获取数据的 Observable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54002758/