Frallen
Frallen

Reputation: 433

async/await with firebase storage

I have a function that receives data, I use an asynchronous promise to get a link to the document item.poster = await Promise.all(promises), then the data does not have time to be added to the array and I get an empty array. But if I remove the function where I get the link to the document, then everything works fine. In debug mode, I can see all the data fine, but why am I getting an empty array?

 async FetchData({ state, commit }, to) {
      try {
      
        const q = query(collection(db, to));

        await onSnapshot(q, (querySnapshot) => {
          let data = [];

          querySnapshot.forEach(async (doc) => {

            let promises = [];
            let item = {
              id: doc.id,
              name: doc.data().name,
              slug: doc.data().slug,
              country: doc.data().country,
              duration: doc.data().duration,
              year: doc.data().year,
              video: doc.data().video,
              genres: doc.data().genres,
              actors: doc.data().actors,
            };
            if (to === "films") {
              const starsRef = ref(storage, `images/${doc.id}/poster.png`);

              promises.push(getDownloadURL(starsRef));
              item.poster = await Promise.all(promises);
            }
            data.push(item);
          });
          commit("setData", { data, to });
        });
      } catch (err) {
        console.error(err);
      } }

enter image description here

Upvotes: 2

Views: 257

Answers (1)

Sergey Sosunov
Sergey Sosunov

Reputation: 4600

forEach and async do not work nice together, forEach is not awaitable. But the solution is simple, .map and Promise.all():

// async not really needed
async FetchData({ state, commit }, to) {
  const q = query(collection(db, to));
  // TODO: Call the unsubscribeFn method in order to stop
  // onSnapshot callback executions (when needed)
  const unsubscribeFn = onSnapshot(q, (querySnapshot) => {
    const allPromises = querySnapshot.docs.map(async (doc) => {
      const docData = doc.data();
      let item = {
        id: doc.id,
        name: docData.name,
        slug: docData.slug,
        country: docData.country,
        duration: docData.duration,
        year: docData.year,
        video: docData.video,
        genres: docData.genres,
        actors: docData.actors
      };
      // Or you can use
      // let item = { id: doc.id, ...docData };
      if (to === "films") {
        const starsRef = ref(storage, `images/${doc.id}/poster.png`);
        item.poster = await getDownloadURL(starsRef);
      }
      return item;
    });
    Promise.all(allPromises)
      .then((data) => commit("setData", { data, to }))
      .catch(console.error);
  });
}

Upvotes: 2

Related Questions