J V J V - 1 month ago 14
Javascript Question

Proper mindset for use of promises?

I've only recently looked at promises (JS not being my forte) and I'm not sure what the proper way to do this is. Promises are supposed to prevent right-drifting code but when I end up with somewhat complex logic I end up nested far too deep anyway, so I'm convinced I'm doing it wrong.

If I'm returning both successes and failures as json values, and I want to handle malformed json as well, I immediately think to do something like this:

fetch('json').then(function (result) {
return result.json();
}).catch(function (result) {
console.error("Json parse failed!");
console.error(result.text);
}).then(function (wat) {
// if (!result.ok) { throw...
}).catch(function (wat) {
// Catch http error codes and log the json.errormessage
});


Of course, this won't work. This is stereotypical synchronous code. But it's the first thing that comes to mind. Problems I can see:


  • How do I get both the response and the json output?

  • How do I get separate control flow for errors and successes?

  • How do I catch a json parse error on both types of response?



My best attempt involves nesting to the point where I might as well be using callbacks, and it doesn't work in the end because I still haven't solved any of the above problems:

fetch('json').then(function (response) {
if (!response.ok) {
throw response;
}
}).then(
function (response) {
response.json().then(function (data) {
console.log(data);
});
},
function (response) {
response.json().then(function (data) {
console.error(data.errormessage);
});
}
).catch(function () {
console.error("Json parse failed!");
// Where's my response????
});


What's the "Right" way to do this? (Or at least less wrong)

Answer Source

If you want to call response.json() anyway (for successful and failed response) and want to use the response together will the response data. Use Promise.all:

fetch('json')
  .then(response => Promise.all([response, response.json()]))
  .then(([response, data]) => {
    if (!response.ok) {
      console.error(data.errormessage);
    } else {
      console.log(data);
    }
  })
  .catch(err => {
    if (/* if http error */) {
      console.error('Http error');
    } else if (/* if json parse error */) 
      console.error('Json parse failed');
    } else {
      console.error('Unknown error: ' + err);
    }
  });