stormec
stormec

Reputation: 189

How to add properties to object incrementally?

I am trying to map object where correct ID will contain the array that belongs to it.

Here is the scenario:

let obj = {}
const arr = []
for (let i = 0; i < someIds.length; i++) {
  const res = await someApiCall() // returns array
 
 obj = {
    id: someIds[i],
    res
  }

 arr.push(obj)

 return arr

}

The thing here is that arr will only output last set of object because of iterating over the values.

For example I get

[{id: 122, res: "whatever122"}]

where I want to get

[{id: 122, res: "whatever122"}, {id: 111, res: "whatever111"}, {id: 133, res: "whatever133}]

How do I concatenate all?

Upvotes: 0

Views: 71

Answers (3)

axiac
axiac

Reputation: 72256

The problem is produced by the return statement that should probably stay outside the for loop. It completes the execution of the current function and returns (an optional value) to the caller.

A simpler way to write what you need is to use Promise.all() to run all the calls to someApiCall() in parallel (if they are independent). This way the code run much faster:

async function doSomething() {
  return await Promise.all(
    someIds.map(
      async (id) => {
        return {
          id: id,
          res: await someApiCall(id),
        };
      }
    )
  );
}

How it works

someIds.map() calls the callback function that it receives as argument for each item of someIds and returns a new array that contains the values returned by the callback function.

Because the callback function is asynchronous and uses await, it returns a Promise as soon as the await-ed call starts, without waiting it to complete.

The array of promises returned by someIds.map() is passed as argument to Promise.all() that waits for all of them and returns an array containing the values returned by the promises (which are the objects returned by the callback were they be synchronous).

Remark

The await in front of Promise.all() is not really needed. Without it, the function doSomething() returns the promise returned by Promise.all(). With it, the function returns an array of objects. Either way, the call of doSomething() still needs to be await-ed and the value produced by it after await is an array of objects.

Upvotes: 0

Thamognya
Thamognya

Reputation: 153

Move the return statement outside of the for loop, which would wait for all of the objects to get added to the array.

let obj = {}
const arr = []
for (let i = 0; i < someArr.length; i++) {
    const res = await someApiCall() // returns array
    obj = {
        id: res[i],
        res
    }
    arr.push(obj)
}
return arr

Upvotes: 0

Robert-Jan Kuyper
Robert-Jan Kuyper

Reputation: 3326

You return arr to fast. It should be returned outside the for scope:

let obj = {}
const arr = []

for (let i = 0; i < someIds.length; i++) {
  const res = await someApiCall() // returns array
 
  obj = {
    id: someIds[i],
    res
   }

   arr.push(obj)
 }

 return arr

Upvotes: 2

Related Questions