0

I have the following structure in firestore.

• conversations - {convid}

  • messages - {messageId}

  • field array offline [user ids]

• users - {userid} - devices - {deviceids}

So the usecase is whenever a new message is sent by a user, a triggered cloud function checks the offline array containing the userids of all offline users in the group.

Now while iterating and later sending a push to offline users, the iteration only shows multiple queries to the user on the last index of the array in the for loop.

The logs in cloud function are

The array of offline users is => [ '919XXXXX5565', '919XXXXX9334', '9190XXXXX608','919XXXXX1818', '919XXXXX9974', '9197XXXXX661', '9181XXXXX854' ]

2:56:22.043 AM Current user id: 919XXXXX5565

2:56:22.044 AM Current user id: 919XXXXX334

2:56:22.044 AM Current user id: 9190XXXXX608

2:56:22.044 AM Current user id: 919XXXXX1818

2:56:22.044 AM Current user id: 919XXXXX9974

2:56:22.044 AM Current user id: 9197XXXXX661

2:56:22.044 AM Current user id: 9181XXXXX854

2:56:22.046 AM Successfully prepared token list false

2:56:22.151 AM Function execution took 5097 ms, finished with status: 'ok'

2:56:22.188 AM No matching documents. for => 9181XXXXX854

2:56:22.190 AM No matching documents. for => 9181XXXXX854

2:56:22.229 AM No matching documents. for => 9181XXXXX854

2:56:22.231 AM No matching documents. for => 9181XXXXX854

2:56:22.233 AM No matching documents. for => 9181XXXXX854

2:56:22.237 AM No matching documents. for => 9181XXXXX854

My Code

var outputList = [];
var promises = [];   
return admin.firestore().collection('conversations').doc(conversationDocId).get();
    .then(document =>{
              let offline = []
              if(!document.exists){
                  return false;
              } else{
                  try{
                    offline = document.data().offline;
                    console.log("The array of offline users is =>", offline);
                  }catch(offlineError){
                    console.error("offline array does not exist" + offlineError);
                  }

                  for(uid of offline) {
                    console.log("Current user id: " + uid);
                    let promise = admin.firestore().collection("users").doc(uid).collection('devices').get()
                        .then(snapshot => {
                            if (snapshot.empty) {
                                console.log('No matching documents. for =>', uid);
                            }
                            snapshot.forEach(doc => {
                                try {
                                    token = doc.data().rt
                                    outputList.push(token);
                                } catch (tokenfetcherror) {
                                    console.error("unable to fetch token for =>", uid);
                                }
                            });
                            return;
                        }).catch(errtoken => {
                            console.error('Error getting documents', errtoken);
                        });
                    promises.push(promise);
                }

                Promise.all(promises).then(() => {
                    return outputList;
                }).catch(err => {
                    return err;
                })
              }
              return false;
          })

I picked this from https://stackoverflow.com/a/57739544/1468797

5
  • 1
    Your function needs to return a promise that resolves only after all other promises have resovled from the async work you started. Commented Apr 17, 2020 at 22:35
  • I think it's doing that, the problem looks to be more with just the logging. I am using uid in the log, which is outside the asynchronous execution. and thus it's only picking the last value in the iteration Commented Apr 18, 2020 at 5:48
  • Moreover this is a almost the same code as in the answer link above. but the part3 video from you video tutorial really heled clean this up. Thanks Doug Commented Apr 18, 2020 at 5:55
  • 1
    You're ignoring the promise returned by Promise.all(). Returning false is not the thing to do when you have nested promises. Commented Apr 18, 2020 at 5:56
  • yes fixed that already after looking at the video. btw is nesting promises inside a for loop a good practice? I think I saw a warning regarding this while building Commented Apr 18, 2020 at 6:01

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.