У меня есть метод в моей службе, внутри которого я пытаюсь вернуть Observable объекта User. Вот мой код -
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.info(user); // has the data
// return user; // doesn't work, not the right thing
}));
console.info(user); // undefined, since call is async
return of(user);
}
Внутри компонента мне нужны эти данные для следующих шагов, поэтому я сделал это -
checkEmail() {
var user$: User
this.us.getUserByEmail(this.existingUserForm.value.email).subscribe(user => {
console.info(user);
if (user) {
this.msg$ = "success";
// next steps
}
else {
this.msg$ = "User with this email does not exist!";
}
});
}
Я не уверен, как вернуть наблюдаемое из моей службы, чтобы я мог использовать данные в своем компоненте. И правильно ли это делать то, что я пытаюсь сделать?





Если вам нужна наблюдаемая из Firestore, вам нужно вернуть .valueChanges () в AngularFirestoreCollection. Прочтите этот документ для справки: 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.info(user);
return user;
})
);
return user$;
}
Если вы хотите, чтобы идентификатор был у вашего пользователя, вам нужно использовать snapshotChanges (). Иногда проще сохранить идентификатор в пользовательских данных при сохранении в firestore, чтобы избежать использования snapshotChanges (на мой взгляд).
// 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 protected]')
.pipe(
tap(user => {
if (user) {
this.msg = 'success';
} else {
this.msg = 'User with this email does not exist!';
}
}));
}
Обратите внимание, что пользователь будет нулевым до тех пор, пока вы не вызовете subscribe для this. User $ OR в вашем html используйте асинхронный канал, который обрабатывает подписку и отмену подписки для наблюдаемого.
<div *ngIf = "(user$ | async) as user">{{ user.email }}</div>
Старайтесь избегать использования асинхронного канала для одного и того же наблюдаемого несколько раз в вашем html и вместо этого установите его как локальную переменную html, что я делаю выше (как пользователь), чтобы избежать ненужных поездок данных в db
Замечание о соглашения об именах. Имена переменных наблюдаемых часто имеют суффикс «$», в то время как другие (строка, числа и т. д.) Не имеют символа «$».
Правильно, это немного сложнее, но я отредактирую исходный ответ, чтобы показать код.
Создать услугу:
constructor(private db: AngularFirestore) { }
getCategories() {
return this.db.collection('categories').valueChanges();
}
используй это:
categories$;
constructor(categoryService: CategoryService) {
this.categories$ = categoryService.getCategories();
}
отображать ваши документы:
<select id = "category" type = "text" class = "form-control">
<option value = ""></option>
<option *ngFor = "let c of categories$ | async" [value] = "c.$key">
{{ c.name }}
</option>
</select>
Спасибо за ответ, но мне также нужен идентификатор пользователя, который valueChanges не возвращает, будет ли это работать, если я использую изменения снимка?