Как получить Observable для данных из запроса Firestore в Angular 7? - PullRequest
0 голосов
/ 02 января 2019

У меня есть метод в моем сервисе, внутри которого я пытаюсь вернуть объект 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.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!";
      }

    });

  }

Я не уверен, как вернуть наблюдаемое из моего сервиса, чтобы я мог использовать данные в своем компоненте. И это правильный способ сделать то, что я пытаюсь сделать?

1 Ответ

0 голосов
/ 02 января 2019

Если вы хотите, чтобы наблюдаемое из Firestore, вам нужно вернуть .valueChanges () для AngularFirestoreCollection.Прочитайте этот документ для справки: https://github.com/angular/angularfire2/blob/master/docs/firestore/querying-collections.md.

В вашем сервисе выполните: (Я объявил переменные коллекции и пользователя $ для ясности).

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$;
}

Если вы хотите, чтобы идентификатор былхорошо для вашего пользователя вам нужно использовать 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@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 часто добавляется суффикс «$», в то время как другие (строка, числа и т. Д.) Не имеют «$».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...