Tyler C
Tyler C

Reputation: 531

Promise trouble! How can I write this in such a way that it waits for the end?

Trying to write this in a way that it will wait for the db operations to complete. Possible?

function addFriendsToSession(session, sessionId) {
    const friends = [];

    const incoming = session.users.forEach(async user => {
        console.log('user', user);
        await db
            .collection('users/' + user + '/settings')
            .doc(user)
            .get()
            .then(doc => {
                if (doc.exists) {
                    const returnObj = doc.data();
                    return returnObj.friends ? returnObj.friends : [];
                } else {
                    return [];
                }
            });
    });
    friends.push(incoming);
    return friends;
}

Upvotes: 0

Views: 71

Answers (2)

chris
chris

Reputation: 16443

Use Promise.all.

Promise.all accepts an array of promises, and resolves once each promise has resolved. You can map your operation using map. E.g.,

const promises = session.users.map(user => {
    console.log('user', user);
    return db
        .collection('users/' + user + '/settings')
        .doc(user)
        .get()
        .then(doc => {
            if (doc.exists) {
                const returnObj = doc.data();
                return returnObj.friends ? returnObj.friends : [];
            } else {
                return [];
            }
        });
});

const friends = await Promise.all(promises)

return friends;

Upvotes: 1

Codebling
Codebling

Reputation: 11382

There are a number of issues here.

  1. In db.then(), return is used, but this value is never returned from the function that encloses it (which is async user => {...})
  2. const incoming is assigned the result of session.users.forEach, but Array.forEach() never has a return value (you may be thinking of Array.map()?)
  3. Even if you solved the first two problems, incoming would still be an array of Promises

Additional suggestions:

  • Don't mix async/await with .then

Putting it all together:

const incoming = session.users.map(async user => {
    console.log('user', user);
    const doc = await db
        .collection('users/' + user + '/settings')
        .doc(user)
        .get();
        //we assigned `doc` using await instead of using .then
    if (doc.exists) {
        const returnObj = doc.data();
        return returnObj.friends ? returnObj.friends : [];
    } else {
        return [];
    }
});
//incoming is not an array of Promises
const incomingFriends = await Promise.all(incoming); //takes an array of Promises and returns an array of the resolved values
//incomingFriends is now an array of friends

//next line would make the last element an array
//friends.push(incoming); 
//you probably want to push every element of the array
friends.push(...incomingFriends);

Upvotes: 1

Related Questions