Promise.all returns another promise

Viewed 58

I have the following functions in Javascript:

// fetches the username based on the user ID

const fetchUsername = async (userId) => {
    const response = await axios({ ... });
    return {
        userId,
        username: response.data.username
    }
};

// fetches the online status based on the user ID

const fetchOnline = async (userId) => {
    const response = await axios({ ... });
    return {
        userId,
        online: response.data.online
    }
};

const fetchUsers = (userIds) => {
    const promises = [];
    userIds.forEach(userID => {
        return new Promise(async (resolve, reject) => {
            const usernameObject = await fetchUsername(userId);
            const onlineObject = await fetchOnline(userId);
            resolve({ ...usernameObject, ...onlineObject });
        })
    })
    Promise.all([promises]).then(response => console.log(response));
};

I have 2 questions about this piece of code:

  1. the response in Promise.all().then() is another promise. It's not an array with objects containing usernames and online statuses, but promises (like this: {"_40": 0, "_55": null, "_65": 0, "_72": null}).

  2. using async/await in new Promise is anti-pattern, but I have no idea how I can combine the results of the 2 promises to 1 object.

EDIT:

I can only accept one answer, but the answer from Gabriel Donadel Dall'Agnol helped me with question 1 and the answer from Klaycon helped me with question 2.

Thank you very much everybody!

2 Answers

You just missed populating the promisesarray

const fetchUsers = (userIds) => {
const promises = userIds.map(userID => {
    return new Promise(async (resolve, reject) => {
        const usernameObject = await fetchUsername(userId);
        const onlineObject = await fetchOnline(userId);
        resolve({ ...usernameObject, ...onlineObject });
    })
})
Promise.all(promises).then(response => console.log(response));
};

In addition to the other answer and comments about populating the promises array and not wrapping it in another array [promises]:

using async/await in new Promise is anti-pattern, but I have no idea how I can combine the results of the 2 promises to 1 object.

This is a convenient use case for Array#map with an async callback. If you mark the callback async, it automatically returns a Promise that will resolve with the return value. So you can write it like this:

const promises = userIds.map(async userID => {
    const usernameObject = await fetchUsername(userId);
    const onlineObject = await fetchOnline(userId);
    return { ...usernameObject, ...onlineObject };
});

Promise.all(promises).then(response => console.log(response));
Related