Christoffer Endresen
Christoffer Endresen

Reputation: 39

Asynchronous code returns empty array (Firestore and VueJS)

I`m using Firestore as database and VueJS as Javascript framework.

The goal:

  1. I got one collection where all fotball players are represented by individual documents. I get a list of all available fotball players.

  2. Get all statistics that exists on available fotball players.

  3. Combine (aggregate) all statistics for per fotball player for all matches played.

The problem is that this.aggregatedPlayerStats returns as an empty array. I suspect it has to do with asynchronous code, as it works if I trigger the aggregatePlayerStats() method on a button.

Code:

export default {
  name: "AggregatedAllTimeStats",
  data() {
    return {
      allPlayers: [],
      allStats: [],
      aggregatedPlayerStats: []
    };
  },
  async created() {
    await this.getAllPlayers();
    await this.getAllStats();
    this.aggregatePlayerStats();

  },
  methods: {
    async getAllPlayers() {
      return db.collection("players").get().then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
          this.allPlayers.push({
            playerid: doc.id,
            name: doc.data().name,
            playerstatus: doc.data().playerstatus
          })
        })
      })
    },
    getAllStats() {
      this.allPlayers.forEach((player) => {
        return db.collection("playerstatsformatch").where("playerid", "==", player.playerid).get().then((querySnapshot) => {
          querySnapshot.forEach((doc) => {
            this.allStats.push(doc.data())
          })
        })
      })
    },
    aggregatePlayerStats() {
      const aggregatedResults = Object.values(
        this.allStats.reduce((a, c) => {
          if (!a[c.playerid]) {
            a[c.playerid] = {
              goals: c.goals,
              name: c.name,
              assists: c.assists

            };
          } else {
            a[c.playerid].goals += c.goals;

          }
          return a;
        }, {})
      );
      this.aggregatedPlayerStats = aggregatedResults
      console.log(this.aggregatedPlayerStats)
    }
  },
};

Upvotes: 0

Views: 37

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 600131

Your getAllStats doesn't return any promise from its outer loop, so there's nothing to await for when calling it. As always, the solution to wait for multiple promises is to use Promise.all.

This should be closer:

getAllStats() {
  return Promise.all(this.allPlayers.map((player) => {
    return db.collection("playerstatsformatch").where("playerid", "==", player.playerid).get().then((querySnapshot) => {
      querySnapshot.forEach((doc) => {
        this.allStats.push(doc.data())
      })
    })
  }))
},

Upvotes: 1

Related Questions