简体   繁体   中英

Return nested Promise.all result in firebase function onCall

I'm creating a cloud function that receives a call from the client including the current user id. What I'm trying to achieve is get a list of friend ids from the "users" collection under the current user id and then for each friend id get a list of objects from a collection named "locations". The code below has the correct queries but there is some confusion around the promise handling and the return statements. How can I correctly return the result from inside the second 'then' ? Currently returning HttpsCallableResult with data as an empty map even thought it should include 2 objects.

exports.friendsData = functions.https.onCall((data, context) => {
    return admin
        .firestore()
        .collection('users')
        .doc(data.id)
        .get()
        .then(snapshot => {
            const friendsIds = snapshot.data().friends;
            console.log('friendsIds', friendsIds);

            return Promise.all(
                friendsIds.map(id => {
                    console.log('id', id);
                    return admin
                        .firestore()
                        .collection('locations')
                        .where('userid', '==', id)
                        .get();
                })
            );
        })
        .then(locationSnapshots => {
            const results = [];
            for (const locationSnap of locationSnapshots) {
                const data = locationSnap.data();
                console.log('data', data);

                results.push(data);
            }
            console.log('resuts', resuts);
            return resuts;
        })
        .catch(reason => {
            return reason;
        });
});

EDIT locations collection has documents with the autogenerated ids and each document has field named "userid" which is used for the where query Image for location collection structure

Updated code based on comments. locationSnapshots should be an array of query snapshots for each promise added before. Still getting undefined.

I'll document the things wrong we've discovered so far in an answer:

First, you need a .get() after the .where(...) to get the promise.

Second, if friendsIds is an array and you're trying to iterate the contents of the array, change this:

for (const id in friendsIds)

to this:

for (const id of friendsIds)

When you use in , it iterates properties of the object which in the case of an array would be the array indexes, not the array values.

Even better would be switch to use .map() since you're trying to create an array from an array. Change this:

        const promises = [];
        for (const id in friendsIds) {
            const p = admin
                .firestore()
                .collection('locations')
                .where('userid', '==', id)
                .get();
            promises.push(p);
        }

        return Promise.all(promises);

to this:

        return Promise.all(friendsIds.map(id => {
            return admin
                .firestore()
                .collection('locations')
                .where('userid', '==', id)
                .get();
        }));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM