Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Promise.all on an array of objects and then reassign them to the relevant key in a new object? [duplicate]

I'm a bit stuck on the middle portion of my code. I know what I want the end to look like, and the beginning, but cannot seem to fill in the blank.

I call fetch on 4 API endpoints, and store the Promises into a relevant key that tells me what they are.

Then I loop through all of those using a for in loop, and push all those Promises into an array so I can call Promise.all on them.

After successfully logging the array to the console, I see now that the array is filled with objects with my data. However, there is no way for me to tell which data belongs to what object key, like in the original object.

Is there a better way to do this? I do know for a fact that I want to use Promise.all here in this code; that's something I don't want to budge on, because I am trying to figure out how I can make this possible without giving up (been at this for a couple hours now).

At the end of my code (this is just pseudocode for a real life example in my React app), I just want to take the final object, and push it into state.

Any help is appreciated.

//imitating React State as an example
const state = {
  iliakan: '',
  remy: '',
  jeresig: '',
}

//put all of the urls in an object with a key-pair value to describe the data
const githubAPI = {
  iliakan: 'https://api.github.com/users/iliakan',
  remy: 'https://api.github.com/users/remy',
  jeresig: 'https://api.github.com/users/jeresig'
}

//create an empty object to assign promises to keys
const movieData = {};
const promiseArr = [];
//store promise into relevant key
for (const user in githubAPI) {
  movieData[user] = fetch().then(res => res.json())
}
//now movieData has keys with values set to related Promises
console.log(movieData);
//loop through these promises, and put them in an Array for Promise.all
for (const userData in movieData) {
  promiseArr.push(movieData[userData])
}

//Use Promise.all on all of those promises
Promise.all(promiseArr).then(responseArr => console.log(responseArr);

//this is where I am stuck. I now have an array of objects with all the correct data, but I don't know how to reassign them back to their original, matching key that they had in the movieData object!


//end goal is to have an object like this
//const movieData = {
//  iliakan: {//object with data from api},
//  remy: {//object with data from api},
//  jeresig: {//object with data from api}
//}

//use the movieData to setState and update current component state
like image 774
Phillip Choi Avatar asked Sep 12 '25 06:09

Phillip Choi


1 Answers

A way to do this, is by seeing the "connection between a key and a property" as it's own "thing" in programming: a key-value pair. The javascript API calls them "entries", and uses a simple 2 element array as the "thing": ['key', 'value'] would be key: 'value'.

You can go from an object to entries with Object.entries(the_object). It will return an array with "entry-array"-s inside it:

const githubAPI = {
  iliakan: 'https://api.github.com/users/iliakan',
  remy: 'https://api.github.com/users/remy',
  jeresig: 'https://api.github.com/users/jeresig'
}

let githubEntries = Object.entries(githubAPI)
// githubEntries = [
//   ['iliakan', 'https://api.github.com/users/iliakan'],
//   ['remy', 'https://api.github.com/users/remy'],
//   ['jeresig', 'https://api.github.com/users/jeresig'],
// ]

Now you can use this concept, and make the promises also "entries", the result and the key combined in a [key, value] array. This way, you can later rebuild the object from the entries in the Promise.all result.

let promiseOfEntries = Promise.all(Object.entries(githubAPI).map((entry) => {
  let [key, value] = entry;
  return fetch().then(x => x.json()).then(result => {
    // Important step here: We combine the result with the key,
    // into a new [key, value] entry
    return [key, result];
  })
}

let promiseOfResults = promiseOfEntries.then(resultEntries => {
  // From the "entries", we build an object again here
  let results = {};
  for (let [key, value] of resultEntries) {
    results[key] = value;
  }
  return results;
});

promiseOfResults.then(results => {
  // Do anything with results!
  console.log('results:', results);
});

Lodash even has _.fromPairs to do this [ [key, value], [key2, value2], ...] to { key: value, key2: value2 } conversion. https://lodash.com/docs/4.17.11#fromPairs

You can use this concept of "entries" for any place where you juggle between objects and arrays.

Hope I explained it well enough, don't be afraid to ask questions in the comments if I haven't!

like image 200
Michiel Dral Avatar answered Sep 13 '25 20:09

Michiel Dral