0

I want to be able to reject the entire promise chain if anyone of the promise fails in a clean way. I want to "catch" this rejection and send an error notification. I have implemented it the following code:

let reportMetaData = api.ajaxGet(api.buildV3EnterpriseUrl('reports' + '/' + params.report_id))
  .catch(error => {
    if (error.status === constants.HTTP_STATUS.GATEWAY_TIMEOUT) {
      this.notify.error(this.translate('reports.report_timedout'), this.translate('reports.report_timedout_desc'));
    } else {
      this.send('error', error);
    }
  });

let aggregateData = reportMetaData.then(success => {
  try {
    return api.xmlRequest('GET', success.aggregationUrls.elements[0].url);
  } catch (error) {
    return Promise.reject();
  }
}).then(rawData => {
  try {
    return JSON.parse('{' + rawData + '}');
  } catch (error) {
    return Promise.reject();
  }
}, error => Promise.reject(error));

let aggregateReport = aggregateData.then(data => {
  if (!data || !data.report) {
    return Promise.reject();
  }
  return data.report;
}).catch(error =>{ 
    this.notify.error(this.translate('reports.report_timedout'), error); 
});

As you can see, it is super messy and complicated. Is there a way I can simplify this? I want the simplest way to reject the entire promise to fail if anyone promise fails. How do I do that from inside the then function? Also, it seems like the thrown error is bubbling up all the way to chrome console as uncaught error. Why does it bubble up even though I caught it?

CORS noob
  • 61
  • 5
  • am i wrong or arent you already doing this through return Promise.reject() ? I think you can simply leave away some error catchers and it would all go to the last one... – Jonas Wilms May 24 '17 at 21:57
  • 1
    Main problem seems to be that you don't actually have a chain. You have several separate promises that have no relation at all to one another. Do you intend for all your code to be chained together in one promise chain? Your question as it stands now is not answerable because you obviously already know how to reject from inside a `.then()` since you already doing that in multiple places. But, you have to either collect all your promises together with something like `Promise.all()` or you have to actually chain them together into one chain. We have no idea what you intend for the code. – jfriend00 May 25 '17 at 03:22
  • Ok. I modified my question. Hope it is clearer now. Basically I want to make my code cleaner. Btw I do have promises chained together. For example, aggregateReport is "then" with aggregateData and individualReport is also "then" with aggregateData. So, these are chained together. – CORS noob May 25 '17 at 14:57

3 Answers3

1

You need to use Promise.all() and provide the array of promises as input parameter. If one of those promises will fail, all the promises will not be resolved. Here the doc:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

And here a post on SO where you can read about them:

When to use promise.all()?

quirimmo
  • 9,800
  • 3
  • 30
  • 45
0

Try aggregating everything under Promise.all(iterable).

More here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

If this is not quite what you wanted, take a look at Bluebird - fully featured promise library. Here

UPDATE: If you want to reject the entire promise if any of the promises inside the function fails, try implementing:

throw validationError;

Hope it works.

oneturkmen
  • 1,288
  • 1
  • 11
  • 27
  • The OP didn't specify they are using Bluebird. – nem035 May 24 '17 at 21:49
  • Yeah, I sent it just in case if decides. Though, the first link is ES6 related promises. – oneturkmen May 24 '17 at 21:50
  • 2
    You might want to be explicit about that then. Just saying "use this" with a link isn't very useful :) – nem035 May 24 '17 at 21:51
  • Not using Bluebird. I am using ember promise. Promise.all does not work for me. I want to be able to reject the promise from inside the then function. So, I get a result. I validate against certain criteria. If the validation fails, I want to reject the promise. – CORS noob May 24 '17 at 21:53
  • Check here as well. I guess almost the same issue https://stackoverflow.com/questions/21260602/how-to-reject-a-promise-from-inside-then-function – oneturkmen May 24 '17 at 21:57
0

You could use async functions to clean things up a bit. I think you could replace your code with the following.

async function processDataAndReport() {
  try {
    const data = await api.ajaxGet(api.buildV3EnterpriseUrl('reports' + '/' + params.report_id));
    const rawData = await api.xmlRequest('GET', data.aggregationUrls.elements[0].url);
    const { report } = JSON.parse(`{${rawData}}`);                         
  } catch(e) {
    // send notification
  }
}
pizzarob
  • 11,711
  • 6
  • 48
  • 69