6

I'm facing an issue in regards to error handling with Promise.all

I would expect the following code to call the catch part of the chain when one of the getNetworkstuff() Promises fails. But instead it just calls the next then part and the Browser Console shows an uncaught Error.

Promise.all(
    [[getNetworkstuff(url1)],[getNetworkstuff(url2)]]
    //please note that the arrays within the array are larger in my application
    //otherwise I would just use one big array not arrays in arrays
)
.then(function(result){//Stuff worked})
.catch(function(err){//Stuff broke});

function getNetworkstuff(url){
    return new Promise(function(resolve,reject){//here will be awesome network code})
}

I can see that the promise has not fulfilled as the returned result array contains the appropriate rejected promise.

[[PromiseStatus]]: "rejected"
[[PromiseValue]]: Error: HTTP GET resulted in HTTP status code 404.

Can somebody tell me why catch is not called? (I know it is if I just have an Array of Promises in Promise.all() of which one rejects)

Baiteman
  • 535
  • 1
  • 4
  • 14
  • 3
    You have an array of arrays. You will most likely need to call `Promise.all` on each. – Ben Fortune Aug 18 '15 at 12:48
  • 1
    Promise.all takes an array of promises as it's argument, not an array of arrays – Jaromanda X Aug 18 '15 at 12:48
  • Actually, I tried arrays of arrays and it does work trough them dutifully – Baiteman Aug 18 '15 at 12:50
  • Yeah, as everybody says, the first thing to try will be to remove one of those array levels: Promise.all( [ getNetworkstuff(url1), getNetworkstuff(url2) ], ... – fray88 Aug 18 '15 at 12:52
  • I'd love to get rid of one level of arrays but I have about 40 URLs from which I want to load Data. Therefore I have related information in the respective arrays. The [MDN Page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) says that the parameter has to be "an iterable such as an array". An Array in an Array classifies as iterable, doesn't it? – Baiteman Aug 18 '15 at 12:58
  • @Baiteman: Well apparently it doesn't work? :-) And even your `.then` callback, in case of no error, will *not* receive the expected result values, but just an array of arrays (or promises). – Bergi Aug 18 '15 at 13:00
  • @Baiteman Iterable doesn't mean it will be iterable recursively. – Ben Fortune Aug 18 '15 at 13:02
  • @Baiteman: It needs to be an iterable of promises, not an iterable of arrays. – Bergi Aug 18 '15 at 13:05
  • The returned result values are the same format as the input. I have a result like this: [[Promise1,Promise2],[Promise3, Promise 4]]. Some of which are rejected and some of which are fulfilled with the expected data. – Baiteman Aug 18 '15 at 13:07
  • @Baiteman - sure, you may have that ... they're all asynchronous? seeing as your `Stuff Worked` code will be executed on the next event loop (i.e. within milliseconds one would assume), there's no guarantee that all those promises will be fulfilled/rejected ... is there? – Jaromanda X Aug 18 '15 at 13:11
  • Yeah, I was just reading through your answer... So basically Promise.all doens't wait for the promises within the arrays to finish? – Baiteman Aug 18 '15 at 13:14

1 Answers1

2

Look at your console

function getNetworkstuff(url) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('resolving', url);
            resolve(url);
        }, 5000);
    });
}
Promise.all([[getNetworkstuff('url1')],[getNetworkstuff('url2')]])
.then(function(result){
    console.log('It worked', result);
})
.catch(function(err){
    console.log('It failed', result);
});

Notice it outputs "It worked", 5 seconds BEFORE anything is resolved

Promise.all([getNetworkstuff('url1'), getNetworkstuff('url2')])
.then(function(result){
    console.log('It worked', result);
})
.catch(function(err){
    console.log('It failed', result);
});

Now compare without the array of array - notice the difference in what is logged next to It Worked in both cases

and finally, run this

function getNetworkstuff(url) {
    return new Promise(function(resolve, reject) {
        if(url == 'url1') {
            setTimeout(function() {
                console.log('resolving', url);
                resolve(url);
            }, 5000);
        }
        else {
            console.log('rejecting', url);
            reject(url);
        }
    });
}

Promise.all([getNetworkstuff('url1'), getNetworkstuff('url2')])
.then(function(result){
    console.log('It worked', result);
})
.catch(function(err){
    console.log('It failed', result);
});

Your followup question: how are they kicked of if not being recognized as promises

Can you see that the code below is of a similar pattern to what you are doing with your array of array of results of functions that may or may not return promises? Anyway, take away the promises and the then stuff ... and you've got this

function fn(s) {
    return s.toUpperCase();
}
function fn2(arr) {
    console.log(arr); // [["A"], ["B"]]
}
fn2([[fn('a')],[fn('b')]]);
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • Just a quick follow up question if you don't mind. If Promise.all doesn't recognize the contents of the arrays as promises to wait on before calling then, how are they kicked of if not being recognized as promises? – Baiteman Aug 18 '15 at 13:19
  • Best explained here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all – Jaromanda X Aug 18 '15 at 13:25
  • Thanks for answering my question. I've read the Mozilla page and haven't found the answer to my follow up question but I appreciate the time for answering both of my questions. – Baiteman Aug 18 '15 at 13:29
  • I've added some more info in the answer - I think I know what you may be asking in the follow up and that MDN page probably didn't explain all of it (the MDN page explains what happens if you pass a non-Promise to Promise.all) – Jaromanda X Aug 18 '15 at 13:31
  • Okay, I think I've got an idea, thanks. I'll have to think about it some more then maybe I'll get a full grip on the issue. In the meantime I'll go rewrite my arrays. – Baiteman Aug 18 '15 at 13:52