[Vuejs]-Firebase storage always return Promise

0πŸ‘

βœ…

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

    await onSnapshot(q, (querySnapshot) => {
      const allPromises = querySnapshot.docs.map(async (doc) => {
        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`);
          item.poster = await getDownloadURL(starsRef);
        }
        return item;
      });
      Promise.all(allPromises)
        .then((data) => commit("setData", { data, to }))
        .catch(console.error);
    });
  } catch (err) {
    console.error(err);
  }
}
πŸ‘€Frallen

4πŸ‘

You should use Promise.all() as follows:

const promises = [];
querySnapshot.forEach((doc) => {
     const starsRef = ref(storage, `images/${doc.id}/poster.png`);

     promises.push(getDownloadURL(starsRef));
});

const urlsArray = await Promise.all(promises);
πŸ‘€Renaud Tarnec

1πŸ‘

Map the documents collection to an array of promises that resolve with the full item data, including download URL and await them all with Promise.all().

You’re also registering a real-time updates listener which seems counter to what you seem to want FetchData to do. I would suggest you want to use getDocs() instead of onSnapshot()

async FetchData({ state, commit }, to) {
  try {
    commit("setLoading", true);

    // `onSnapshot` registers a real-time updates listener,
    // use `getDocs` to retrieve documents
    const { docs } = await getDocs(query(collection(db, to)));

    // Map over the `docs` array and return fully hydrated objects
    const data = await Promise.all(
      docs.map(async (doc) => ({
        ...doc.data(),
        id: doc.id,
        poster:
          to === "films"
            ? await getDownloadURL(ref(storage, `images/${doc.id}/poster.png`))
            : null,
      }))
    );

    commit("setData", { data, to });
  } catch (err) {
    console.error(err);
  } finally {
    commit("setLoading", false);
  }
},

If you did want to register a real-time updates listener, do so in an effect hook where you can also remove the listener in a cleanup

useEffect(() => {
  // Return the unsub function as cleanup
  return onSnapshot(query(collection(db, to)), async ({ docs }) => {
    try {
      const data = await Promise.all(
        docs.map(async (doc) => ({
          ...doc.data(),
          id: doc.id,
          poster:
            to === "films"
              ? await getDownloadURL(
                  ref(storage, `images/${doc.id}/poster.png`)
                )
              : null,
        }))
      );

      commit("setData", { data, to });
    } catch (err) {
      console.error(err);
    }
  });
}, [to]);
πŸ‘€Phil

Leave a comment