映射Angular订阅以同步执行 [英] Map Angular subscriptions to execute synchronously

查看:58
本文介绍了映射Angular订阅以同步执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试映射新数组,但需要等到订阅完成后才能返回值.正确的方法是什么?我可以将这些转换为诺言吗?怎么样?

I'm trying to map a new array but need to wait until the subscriptions are done before returning the value. What's the correct way to do this? Can I convert these into promises? How?

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();
  }
}

**更新***

我尝试关注,但对此this.pollVotes不确定.另外,重要的一点是,我必须保持this.firebaseService.getPollVotes的订阅有效,因为每次创建新的投票时,我都需要更新该订阅.

I tried to following but I'm getting undefined for this.pollVotes. Also, it's important that I keep the subscription alive for this.firebaseService.getPollVotes because I need this to update each time a new vote is created.

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

}

**另一个更新**

** ANOTHER UPDATE **

我对函数进行了一些重新排列,现在我在this.pollVotes数组中得到两个条目,但是该数组对两个值都返回未定义的状态,因为forkJoin上的订阅从未被命中.换句话说,我的两个控制台日志语句从不注销.

I re-arranged the function a bit and now I am getting two entries in the this.pollVotes array, however the array returns undefined for both values because the subscription on the forkJoin never gets hit. In other words, my two console log statements never log out.

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

推荐答案

解决了以下问题:

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

这篇关于映射Angular订阅以同步执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆