1

I have this code:

 _getSupport()
.then((data) => {                   
    _getSupport(data[0])
        .then(() => _getSupport(data[1])    
})
.catch(e => {
      console.log(e);
});

_getSupport return a Promise. My goal is to call again _getSupport on values returned the first time. So I tought:

_getSupport()
.then((data) => {       
    let a = [];
    data.forEach(element => {
        a[element] = _getSupport(element)   
      });
      Promise.all(a).then().catch(e => {
      });
 })
 .catch( e => {console.log(e)})

But this does not work, the code always goes to the last catch.

UPDATE

The getSupport() is of this form

function _getSupport(param = {}) {       

    return new Promise((resolve, reject) => {           
        remoteClient.sendRequest(request, function (data) {             
            resolve(data);
        });
    });
}    
gdm
  • 7,647
  • 3
  • 41
  • 71
  • 2
    What is console logged in the last catch? It could be that `_getSupport()` return error from the start, or data is not an array, for example. – Georgy Nov 13 '18 at 17:50
  • 1
    I omitted the code, but data is always an array. The error e is empy. – gdm Nov 13 '18 at 17:54

5 Answers5

2

Here lies the problem

let a = [];
data.forEach(element => {
  a[element] = _getSupport(element)   
});

Since the data can have virtually anything in it; numbers, objects, strings anything, So when you set a[element] you are actually setting that particular property for the array.

a = []
a['see_this?'] = 'does this even make sense?'

You get the point.

What you ought to do is

let a = [];
data.forEach(element => {
  a.push(_getSupport(element))
});
// or
a = data.map(element =>_getSupport(element));

and then use your Promise.all; of course if this is piece of function code you need to return it so others can .then() on it, so return Promise.all()

Prasanna
  • 4,125
  • 18
  • 41
  • 1
    If `element` is a number and `_getSupport()` returns an array of numbers like this `[0,1,2,3]` then using `a[0]`, `a[1]` etc should be just fine no? – Akrion Nov 13 '18 at 17:58
  • 1
    @Akrion yes that would work perfectly fine. But the array must contain `numbers` and not `strings`. – Prasanna Nov 13 '18 at 18:00
  • 1
    @Akrion may be your `_getSupport` is throwing an error in the first place and hence you are going to the last catch. It would be great if you edit your question with your `_getSupport` function as well as the nature of `data` – Prasanna Nov 13 '18 at 18:02
1

This answer is almost identical to other answers, just two cents: you can use .map instead of forEach and push.

let getPromiseObj = data => new Promise((resolve, reject) =>
  setTimeout(
    () => resolve(data || ['No', 'truthy', 'data']),
    1000
  )
)

getPromiseObj()
  .then(res => Promise.all(res.map(getPromiseObj)))
  .then(finalRes => console.log(finalRes))
  .catch(e => console.error(e))
Georgy
  • 2,410
  • 3
  • 21
  • 35
0

If you _getSupport is valid and does not throw an error to begin with you could also modify your code to something like this:

_getSupport()
  .then(data => {
    let a = [];
    data.forEach(element => a[element] = _getSupport(element))
    return Promise.all(a).then().catch(e => {})
  })
  .catch(e => console.log(e))

Where you also return the last Promise.all

Akrion
  • 18,117
  • 1
  • 34
  • 54
0

Sometimes nested promises creates problems.

We need to accumulate promises into an array so that you can return them all. That's why a.push() which will push the promises to the array.

The data in the next .then() function is an array of responses of each promise in the same order they are pushed.

Add console.log(data) to see on what values you are iterating on further.If data cannot be iterated then it might throw error.

Try to execute the "_getSupport()" function individually and see if you are getting any errors, if not then try my code it will work.

    _getSupport()
     .then((data) => {       
         let a = [];
         data.forEach(element => {
         a.push(_getSupport(element))
         });
         return Promise.all(a)
      })
     .then((data) => {
      // If it returns an array of elements then this data will be
      // [[0,1,2],[1,2,3] ...] based on the number of elements returned in 
      // first call
      })
     .catch( e => {console.log(e)})
0

Although all answers stimulated my brain, neither worked as expected. The only solution I found stem from this answer :

 _getSupport() 
 .then((data) => {
                let sTypes = data.parameter.supported_types || [];
                sTypes.reduce((p,value,currentIndex) => {
                    return p.then(() => _getSupport({ method: "get_supported_scale", sType: value }));
                },Promise.resolve());                    
            })          
 .catch(e => {
        logger.error(e.stack);
  });
gdm
  • 7,647
  • 3
  • 41
  • 71