0

I have an array and I need, for each element of this array, to fetch some data (dependent on the element) and add this data to the element in the array.

To set an example, I will simulate the fetch with a Promise (in real life, this will be the answer of a webservice):

let p = new Promise((resolve, reject) => resolve('x'))
let a = ['a', 'b']
a = a.map(x => p.then(y => x + y))
console.log(a)

What I expected is to have for the first element (a) p being called, and upon resolution the result added to a (giving ax). Same for b.

Ultimately I expected a new array ['ax', 'bx'].

What I get instead is an array of Promises

Being quite new to Promises (which I find in theory wonderful) I have a hard time understanding what went wrong here. Is it possible to combine .map() and asynchronous actions within?

WoJ
  • 27,165
  • 48
  • 180
  • 345
  • 1
    Yes, it is absolutely possible to perform asynchronous actions inside of a map. However, at best, the result you will get is an array of promises. You then have to use that array to get the results. It isn't possible for the map to return the results directly because the map returns before the results exist. – Kevin B Feb 14 '18 at 20:13
  • Related: https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Kevin B Feb 14 '18 at 20:15
  • Aslo related: https://stackoverflow.com/questions/46626610/array-of-promises – Kevin B Feb 14 '18 at 20:18
  • @KevinB: I belive the second "related" link is exactly my problem. I am still digesting it but it really looks so. Thanks! – WoJ Feb 14 '18 at 20:22
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then – doubleOrt Feb 14 '18 at 20:31

2 Answers2

9

I expected a new array ['ax', 'bx'], but what I get instead is an array of Promises

This is exactly what Promise.all was made for. Of course it doesn't produce a plain array but rather a promise for it, but you cannot avoid that when you're doing anything asynchronous.

const promises = a.map(x => p.then(y => x + y))
Promise.all(promises).then(console.log, console.error)
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
-1

Edit: here's a code that works the way you want it to work:

let p = new Promise((resolve, reject) => resolve('x'))
let a = ['a', 'b']
let c =[]
Promise.resolve(a.map(x => p.then(y => c.push(x + y)))).then(() => console.log(c))

Since p.then returns an empty object your map will return an array of empty objects.

PS: You can refactor the code, It's a little too late in my country so would go to sleep now.

eshunsharma
  • 171
  • 9