4

I'm trying to fetch() a file, and if it fails, i want to try the alternative file.
This nested Promise() feels dirty. What is a better solution?

fetch('file1.csv')
    .then(function(response){
        if (response.status !== 200) {
            throw 'file1 no 200 response';
        }
        return response;
    })
    .catch(function(){
        return fetch('file2.csv')
                .then(function(response){
                    if (response.status !== 200) {
                        throw 'file2 no 200 response';
                    }
                    return response;
                })
    })
    .then(function(response){
        console.log('got file1 or file2, continue... then() ...');
        console.log(response);
    })
    .catch(function(err){
        console.log('both files not found');
    });
GDmac
  • 880
  • 1
  • 9
  • 28

2 Answers2

3

To make it more DRY, you can always use a function.

function getFile(name) {
  return fetch(name)
      .then(function (response) {
        if (response.status !== 200) {
          throw `${name} no 200 response`;
        }
        return response;
      });
}


getFile('file1.csv')
    .catch(function () {
      return getFile('file2.csv');
    })
    .then(function (response) {
      console.log('got file1 or file2, continue... then() ...');
      console.log(response);
    })
    .catch(function (err) {
      console.log('both files not found');
    });
str
  • 42,689
  • 17
  • 109
  • 127
1

There is absolutely nothing wrong with the nested promise chains here - they represent your desired control flow.

Consider how the code would look if written using async/await syntax:

try {
    var response;
    try {
        response = await fetch('file1.csv');
        if (response.status !== 200) {
            throw 'file1 no 200 response';
        }
    } catch(err) {
        response = await fetch('file2.csv');
        if (response.status !== 200) {
            throw 'file2 no 200 response';
        }
    }
    console.log('got file1 or file2:', response);
} catch(err) {
    console.log('both files not found');
}

TBH, I consider .catch() syntax to be actually cleaner for this use case.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • This solution makes the code more flat and readable, but i do favor the promise.catch() approach. Thanks for the answer, because I was unsure, and couldn't find a good example, if this nesting in the catch for an alternative promise, would be an anti-pattern – GDmac Feb 24 '19 at 15:35
  • @GDmac I'm not suggesting that you should use `await` syntax, this is only to demonstrate how your control flow is nested. Nesting promises is *not* an antipattern when it is useful, promises are in fact *designed* to be nestable. – Bergi Feb 24 '19 at 15:51