0

I have one array of promises that each one execute a code that can have a javascript error and break the script. I need to check for each promise and catch any error. The problem is that the promise has timeout functions inside. Is there anyway to solve this?

Example code:

function apiRequest(url,customError) {
  return new Promise(function (resolve, reject) {
    if(customError) {
        setTimeout(() => {
            //Force error
            var ar = url.asdasd.eadasd;
            ar = ar.split('123')
        },3000)
    }
    if (url) {
        return resolve(url);
    } else {
        return reject('apiRequest failed!');
    }
})
.catch(function(err){
    return 'error on javascript code';
});
}
var p1 = apiRequest('urlOne',true);
var p2 = apiRequest(false,false);
var p3 = apiRequest('urlThree');

Promise.all([p1, p2, p3])
   .then(function(res){
       console.log('Promise.all', res);
   }, error => {
       console.log('Error on reject')
   })
   .catch(function(err){
       console.error('err', err);
   });

Result:

  Promise.all [ 'urlOne', 'error on javascript code', 'urlThree' ]
  var ar = url.asdasd.eadasd;
  TypeError: Cannot read property 'eadasd' of undefined

If there is an error inside each promise, my code can catch it but if there is a timeout and the error happends after the promise finish I cant catch it and my code breaks, is there anyway to catch this error?

Tiago Castro
  • 361
  • 2
  • 15

1 Answers1

0

Is there any way to check error in each Promise in promise.all when there is a promise error?

By design, Promise.all() resolves when ALL promises you passed it have resolved or it rejects when any single promise in it rejects. It does not, by design, wait for all promises to resolve or reject and then give you all the results whether they resolved or rejected.

Functionality like that is typically named something like Promise.settle() and you can fairly easily build that type of functionality by just adding a .catch() handler to each promise you pass Promise.all() so that instead of rejecting, it resolves, but with a value that you can later tell that it actually rejected.

You can see several various implementations of .settle() type functionality in this answer:

ES6 Promise.all() error handle - Is .settle() needed?

If there is an error inside each promise, my code can catch it but if there is a timeout and the error happends after the promise finish I cant catch it and my code breaks, is there anyway to catch this error?

The way you have structured your setTimeout(), it is not connected at all to the promise that it is inside of. If you want them connected, then you have to wait to resolve until after the timeout is done and then, and only then, can you know if you should resolve or reject.

Since the code you show inside your setTimeout() looks like pseudo-code (that doesn't actually do anything yet), it's hard for us to see exactly what the point of the setTimeout() is to know exactly what you are trying to achieve and thus what a good suggestion would be.

This answer about using setTimeout() as part of a promise chain might be relevant:

using setTimeout on promise chain.

In that case, the timer is inserted into the promise chain so that things are sequenced before it and after it. As you show it now, it's a completely separate parallel path of execution that has no connection at all to your promise chain.

If all you're trying to do with the setTimeout() is to invoke a timeout if your api request does not return before the timer fires, then you can likely implement that by just calling reject() inside the setTimeout(). If the api request has already completed and already called resolve(), then calling reject() will do nothing at that point. If the api request has not yet finished, then calling reject() will reject the host promise.

jfriend00
  • 580,699
  • 78
  • 809
  • 825