0

Working in NodeJS, I have a function that returns an array of objects. Inside these objects, many fields are populated by awaited promises, returned from an API. However, for some reason, this means that I can't operate within the array at all. For example:

I have a function to fetch from the api,

export async function someFunction(){
  let item = `--API URL HERE--`
  let res = await fetch(item);
  let data = await res.json();
  return data;
}

in another async function, I use that data to built an array of objects, some of the fields of that object being populated with information from that api, called with an awaited function like:

let field = await exportedFile.someFunction();

Once I have that array of objects built, I can log it with console.log(array);, and see the fully populated array. However, console.log(array[1]); returns undefined, as does console.log(await array[1]); further, attempting the spread operator to offload it into another array returns an empty array, and attempting to stringify it results in []. Since console.log(array); does work and does print the correct data, I know its being built at some point, but some whatever reason it appears the array operators refuse to respect await.

What am I doing wrong, and how can I work with this array?

yqlim
  • 6,898
  • 3
  • 19
  • 43
RNPF
  • 231
  • 3
  • 23
  • If `console.log(array)` works but `console.log(array[1]);` is `undefined` then you probably *don't* have an `Array` object but something else (perhaps `Promise`)? – Dai Apr 19 '19 at 17:18
  • Please post your code where you get the `array` object. Also, have you considered using TypeScript instead? (using TypeScript helps eliminate huge classes of bugs relating to incorrect type assumptions when working with Promises) – Dai Apr 19 '19 at 17:19
  • 1
    Sounds like you are logging the array before elements have been added. Seeing all elements of the array in the console, **after** expanding it, but getting `undefined` when trying to access an element is a clear indicator for that. You have to wait until all promises are resolved before accessing the array. Since you are not showing how the array is created and accessed, that's all we can say for now. – Felix Kling Apr 19 '19 at 17:19
  • @dai if that is the case, I am unsure what else it would be. The inspector, at least, believes it to be an array. https://i.imgur.com/jETcLwu.jpg Would it have mutated somewhere? – RNPF Apr 19 '19 at 17:22
  • @FelixKling That is my first instinct as well. However, shouldnt the fact that its gone through... many, many awaits through its lifecycle have unwrapped the promise at some point? promise.all also does not appear to work, though I may be misusing it. – RNPF Apr 19 '19 at 17:23
  • Impossible to tell without seeing your code. But the fact that the console logs `[]` already shows that it's an empty array *at the time the array is logged*. The blue `i` box next to it even informs of the fact that expanding the array shows its *current state*. If the array had elements you would see them in that first line. You can easily verify this by comparing `console.log([])` vs `console.log(['foo'])`. – Felix Kling Apr 19 '19 at 17:25
  • So why, then, does console.log(await arrayofObjects) not await the arrayofObjects before logging, and populates after? Is there any way to make it wait? – RNPF Apr 19 '19 at 17:28
  • `await` really only works on promises. If you `await` a value that is not a promise, the value itself is just returned. An array is not a promise. Again, if you'd post your code we could help you better. – Felix Kling Apr 19 '19 at 17:30
  • My code is rather extremely extensive, and not open source at the time to link the repo. It would be difficult to post all the code, as the objects being built have several hundred fields being populated. I could attempt to replicate the problem in a simplified test repo, however. – RNPF Apr 19 '19 at 17:32
  • Couldn't see array variable in the given code sample. Can you update your post with how you are populating the array? – Sivaprasath Apr 19 '19 at 17:39
  • Figured it out. Not enough awaits. Needed to also await each individual object going into the array. Thanks for the help pointing out the length was 0, helped me find this question: https://stackoverflow.com/questions/44433131/javascript-array-length-of-0 – RNPF Apr 19 '19 at 17:41
  • As an aside, you may want to read up on the [Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) method as well as the [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) operator. – romellem Apr 19 '19 at 17:52

0 Answers0