0

I've got a function that monitors my notifications collection, however within the snapshot, I need to perform an await function.

async function getNotifications() {
    try {
        firebase.firestore().collection("notifications").doc(firebase.auth().currentUser.uid).collection("messages")
            .onSnapshot((qs) => {
                const array = [];
                const promises = [];
                qs.forEach(async(n) => {
                    let data = n.data();
                    data.id = n.id;
                    if(data.type === "download") await storageGetDownloadURL(data.filepath);
                    array.push(data)
                });
                console.log(array)
                return setNotifications(array);
            });
    } catch (e) {
        message.error(e.message)
    }
}

This line is what is causing the issues is if(data.type === "download") promises.push(await storageGetDownloadURL(data.filepath));. If I keep this in, then array is populated, however something is amiss with it. Performing .length on it says its empty when its not etc.

If I remove this line, the array is properly complete.

Is there a way I can perform an await within the snapshot? I've also tried pushing them to an array and calling them after, but still have the same issue.

EDIT: Suggested duplicate question does not work with Firebase snapshots. Throws qs is not iterable

                    for(const n of qs) {
                        let data = n.data();
                        data.id = n.id;
                        if(data.type === "download") await storageGetDownloadURL(data.filepath);
                        array.push(data)
                    }

I have also tried as @Doug Stevenson suggested, however if I log out array and then array.length, I get some strange result where the array is empty, yet contains items, and length also says its empty

Note: I don't have to execute the promises for this to break

   const promises = [];

                qs.forEach(async(n) => {
                    let data = n.data();
                    data.id = n.id;
                    if(data.type === "download") promises.push(await storageGetDownloadURL(data.filepath));
                    array.push(data)
                });
                console.log(array)
                console.log(array.length)

enter image description here

Since this was closed, I managed to get this semi-working by creating new promises within the loop, and executing the afterwards. Whilst the await within the promise doesn't cause issues, it doesn't execute

            firebase.firestore().collection("notifications").doc(firebase.auth().currentUser.uid).collection("messages")
                .onSnapshot(async(qs) => {
                    const array = [];
                    const promises = [];

                    qs.forEach((n) => {
                        promises.push(new Promise(async(res, rej) => {
                            let data = n.data();
                            data.id = n.id;
                            if(data.type === "download") await storageGetDownloadURL(data.filepath);
                            array.push(data);
                            return res();
                        }));
                    });
                    await Promise.all(promises);
                    return setNotifications(array);
                });
K20GH
  • 6,032
  • 20
  • 78
  • 118
  • what if you write `if(data.type === "download"){ await storageGetDownloadURL(data.filepath); }` instead of `if(data.type === "download") await storageGetDownloadURL(data.filepath); ` – Pushprajsinh Chudasama Aug 29 '19 at 20:05
  • You'll need to rewrite your foreach loop to collect a bunch of promises and pass those along to the next thing, which will have to await them. – Doug Stevenson Aug 29 '19 at 20:07
  • I've tried doing `promise.push(await storageGetDownloadURL(data.filepath)` however even just having this 1 line within the loop breaks it, even if I don't perform `Promise.all()` – K20GH Aug 29 '19 at 20:08

0 Answers0