Joan
Joan

Reputation: 729

Failing fetch in a Promise.all not catching error

I have multiple JSON to load and must check if all of them are well fetched. So I use a Promise.all to wait for all the fetch.

The first valid.json exists, not the second one, so the second fetch ends with a 404. But despite the Promise.reject, Promise.all still logs Success! instead of throwing the last Error.

Is there something I missed about how Promise.all works?

const json_pathes = [
    'valid.json',
    'not_valid.json'
];

function check_errors(response) {
    if (!response.ok) {
        Promise.reject('Error while fetching data');
        throw Error(response.statusText + ' (' + response.url + ')');
    }
    return response;
}

Promise.all(json_pathes.map(url =>
    fetch(url)
        .then(check_errors)
        .then(response => response.json())
        .catch(error => console.log(error))
))
.then(data => {
    console.log('Success!', data);
})
.catch(reason => {
    throw Error(reason);
});

// Console:
// Error: "Not Found (not_valid.json)"
// uncaught exception: Error while fetching data
// Array [ […], undefined ]

(Checked all the similar questions of course, but nothing helped 😕)


edit — Fixed code after below answers:

const json_pathes = […]
Promise.all(json_pathes.map(url =>
    fetch(url)
        .then(response => {
            if (!response.ok)
                throw Error(response.statusText + ' (' + response.url + ')');
            return response;
        })
        .then(response => response.json())
        .catch(error => {
            throw error;
        })
))
.then(data => {
    // Success
})
.catch(error => {
    throw error;
});

Upvotes: 2

Views: 1121

Answers (2)

Bad Dobby
Bad Dobby

Reputation: 871

you have to throw error again when you use the .catch() method, or the error will be muted

Promise.all(
  json_paths.map(url => 
    fetch(url)
      .then(response => response.json())
      .catch(err => {
        console.log(err);
        throw err
      })
  )
).then(data => {
  // all promise resolved
  console.log(data)
}).catch(err => {
  // some promise may not be resolved
  console.log(err)
})

Upvotes: 1

trincot
trincot

Reputation: 349956

This call:

 .catch(error => console.log(error))

...will return a fulfilled promise, not a rejected one. Whenever you treat a rejection and you want it to bubble up as a rejection, you should explicitly do that:

 .catch(error => {
       console.log(error);
       throw error; // cascade...
 })

By the way, this has no effect at all

 Promise.reject('Error while fetching data');

... as you don't do anything with this newly created, rejected promise.

Upvotes: 4

Related Questions