Карта Angular подписок для выполнения синхронно - PullRequest
0 голосов
/ 16 апреля 2019

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

this.firebaseService.getPolls().pipe(first()).subscribe((fetchedPolls:any) => {
      this.polls = fetchedPolls.filter(poll => poll.payload.doc.id == this.pollKey)
      this.pollKey = this.polls[0].payload.doc.id;
      this.firebaseService.getPollVotes(this.pollKey).subscribe((fetchedPollVotes:any) => {
        this.pollVotes = fetchedPollVotes.map((poll:any) => {
          let userKey = poll.payload.doc.get('user');
          let choiceKey = poll.payload.doc.get('choice');
          let username;
          let players;
          this.firebaseService.getUser(userKey).pipe(first()).subscribe((user:any) => {
            username = user.payload.get('username');
          });
          this.firebaseService.getChoice(choiceKey).pipe(first()).subscribe((choice:any) => {
            players = choice.payload.get('players');
          });
          return { username: username, choice: players }
        })
      });
    });

firebase.service.ts

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { map, switchMap, first } from 'rxjs/operators';
import { Observable, from } from 'rxjs';
import * as firebase from 'firebase';
import { AngularFireAuth } from '@angular/fire/auth';

@Injectable({
  providedIn: 'root'
})
export class FirebaseService {
  // Source: https://github.com/AngularTemplates/angular-firebase-crud/blob/master/src/app/services/firebase.service.ts
  constructor(public db: AngularFirestore, private afAuth: AngularFireAuth) { }

  getPolls() {
    return this.db.collection('polls', ref => ref.orderBy('createdAt', 'desc')).snapshotChanges();
  }
  getPollVotes(pollKey) {
    return this.db.collection('votes', ref => ref.where('poll', '==', pollKey).orderBy('createdAt', 'desc')).snapshotChanges();
  }
  getUser(userKey) {
    return this.db.collection('users').doc(userKey).snapshotChanges();
  }
  getChoice(choiceKey) {
    return this.db.collection('choices').doc(choiceKey).snapshotChanges();
  }
}

** ОБНОВЛЕНИЕ ***

Я пытался подписаться, но я получаю undefined для this.pollVotes. Кроме того, важно, чтобы я сохранил подписку на this.firebaseService.getPollVotes, потому что мне нужно обновлять ее каждый раз, когда создается новый голос.

this.firebaseService.getPolls().pipe(first()).toPromise().then((fetchedPolls:any) => {
  this.polls = fetchedPolls.filter(poll => poll.payload.doc.id == this.pollKey)
  this.pollKey = this.polls[0].payload.doc.id;
}).then(() => {
  this.firebaseService.getPollVotes(this.pollKey).subscribe((fetchedPollVotes:any) => {
    this.pollVotes = fetchedPollVotes.map((poll:any) => {
      let userKey = poll.payload.doc.get('user');
      let choiceKey = poll.payload.doc.get('choice');
      let getUserObservable = this.firebaseService.getUser(userKey).pipe(catchError((err, caught) => of([])));
      let getChoiceObservable = this.firebaseService.getChoice(choiceKey).pipe(catchError((err, caught) => of([])));
      forkJoin([getUserObservable, getChoiceObservable])
         .subscribe((results:any) => {
        // results[0], results[1], result[2], result[3] is our response from services
        console.log(results);
        return { username: results[0].payload.get('username'), choice: results[1].payload.get('players')}
      });
    });
  });
  console.log("results", this.pollVotes);
});

}

** ДРУГОЕ ОБНОВЛЕНИЕ **

Я немного перестроил функцию, и теперь я получаю две записи в массиве this.pollVotes, однако массив возвращает undefined для обоих значений, поскольку подписка на forkJoin никогда не срабатывает. Другими словами, мои два оператора консоли никогда не выходят из системы.

this.firebaseService.getPolls().pipe(first()).subscribe((fetchedPolls:any) => {
      this.polls = fetchedPolls.filter(poll => poll.payload.doc.id == this.pollKey)
      this.pollKey = this.polls[0].payload.doc.id;
      this.firebaseService.getPollVotes(this.pollKey).subscribe((fetchedPollVotes:any) => {
        this.pollVotes = fetchedPollVotes.map((poll:any) => {
          let userKey = poll.payload.doc.get('user');
          let choiceKey = poll.payload.doc.get('choice');
          let getUserObservable = this.firebaseService.getUser(userKey).pipe(catchError((err, caught) => of([])));
          let getChoiceObservable = this.firebaseService.getChoice(choiceKey).pipe(catchError((err, caught) => of([])));
          forkJoin([getUserObservable, getChoiceObservable])
             .subscribe((results:any) => {
            // results[0], results[1], result[2], result[3] is our response from services
            console.log("username", results[0].payload.get('username'));
            console.log("players", results[1].payload.get('players'));
            return { username: results[0].payload.get('username'), choice: results[1].payload.get('players')}
          });
        });
        console.log("results", this.pollVotes);
      });
    });

Ответы [ 2 ]

0 голосов
/ 18 апреля 2019

Решено со следующим:

ngOnInit() {
    this.getPollData();
  }

  async getPollData() {
    let fetchedPolls = await this.firebaseService
      .getPolls()
      .pipe(first())
      .toPromise();
    this.polls = fetchedPolls.filter(
      poll => poll.payload.doc.id == this.pollKey
    );
    this.pollKey = this.polls[0].payload.doc.id;
    this.getPollVotesData();
  }
  async getPollVotesData() {
    try {
      let getPollVotesProc = this.firebaseService
        .getPollVotes(this.pollKey)
        .pipe(first())
        .toPromise();
      let fetchedPollVotes = await getPollVotesProc;
      fetchedPollVotes.map(async (poll: any) => {
        let userKey = poll.payload.doc.get("user");
        let choiceKey = poll.payload.doc.get("choice");
        let username;
        let players;
        let user = await this.firebaseService
          .getUser(userKey)
          .pipe(first())
          .toPromise();
        let choice = await this.firebaseService
          .getChoice(choiceKey)
          .pipe(first())
          .toPromise();

        players = choice.payload.get("players");
        username = user.payload.get("username");
        this.pollVotes.push({ username: username, choice: players });
        return { username: username, choice: players };
      });
    } catch (error) {
      console.log(error);
    }
  }
0 голосов
/ 16 апреля 2019

Этого можно добиться с помощью rxjs-forkjoin .Вот крошечный пример для вашего случая,

  let getPollsObservable = this.fireBaseService.getPolls().pipe(catchError((err, caught) => of([])));
  let getPollVotesObservable = this.fireBaseService.getPollVotes(pollKey).pipe(catchError((err, caught) => of([])));
  let getUserObservable = this.fireBaseService.getUser(userKey).pipe(catchError((err, caught) => of([])));
  let getChoiceObservable = this.fireBaseService.getChoice(choiceKey).pipe(catchError((err, caught) => of([])));

  this.getServiceSubscription = forkJoin([getPollsObservable, getPollVotesObservable, getUserObservable, getChoiceObservable])
     .subscribe(results => {
    // results[0], results[1], result[2], result[3] is our response from services
    console.log(result);
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...