Shawn Rieger Shawn Rieger - 1 year ago 133
Javascript Question

Am I handling these promises correctly?

Is there a better way to simply catch all errors here or since there are multiple levels in this promise chain with multiple requests I have no other options?

return RequesterService.get('peakBlockIndex', request)
.then(function(res) {
rangeData = res.data;
rangeData.intervals = [];
if (!rangeData.intervals || rangeData.intervals <= 0) {
return $q.reject({ message: 'Request returned no interval data.' });
}

return SiteService.getSite(rangeData.site.id)
.then(function(site) {
if (!site.zoneId) {
return $q.reject({ message: 'Request for zoneId failed for the given site.' });
}

return getDayAheadData(site.zoneId, start, end)
.then(function(data) {
return handleBlockRange(rangeData, data[0].data, data[1].data);
})
.catch(function(err) {
return $q.reject({ message: 'Request for cleared & forecasted data failed for the given site.' });
})
})
.catch(function(err) {
return $q.reject({ message: 'Request for zoneId failed for the given site.' });
})
})
.catch(function(err){
return $q.reject({ message: 'Request for block-range data failed.' });
});
}

Answer Source

From a quick glance you should be able to remove the nesting altogether like follows. Note, that in case of an error, this will always return the message Request for block-range data failed. similar to your code. The reason is, that using a $q.reject() only skips execution of the promise chain until the next catch() handler. As you placed such a handler at the end of your code, all errors will be caught here.

return RequesterService.get('peakBlockIndex', request)
      .then(function(res) {
          rangeData = res.data;
          rangeData.intervals = [];
          if (!rangeData.intervals || rangeData.intervals <= 0) {
              return $q.reject({ message: 'Request returned no interval data.' });
          }

          return SiteService.getSite(rangeData.site.id)
      })
      .then(function(site) {
          if (!site.zoneId) {
              return $q.reject({ message: 'Request for zoneId failed for the given site.' });
          }

          return getDayAheadData(site.zoneId, start, end);
      })
      .then(function(data) {
          return handleBlockRange(rangeData, data[0].data, data[1].data);
      })
      .catch(function(err){
          return $q.reject({ message: 'Request for block-range data failed.' });
      });

Using the newer async/await syntax, one can improve the readability. This time the actually matching error message is returned. (Note, that one could also return the specific error messages using the upper syntax).

async function someRequest( request ){

  let res;
  try{
    res = await RequesterService.get('peakBlockIndex', request);
  } catch(e){
    return $q.reject({ message: 'Request for block-range data failed.' });
  }

  rangeData = res.data;
  rangeData.intervals = [];
  if (!rangeData.intervals || rangeData.intervals <= 0) {
    return $q.reject({ message: 'Request returned no interval data.' });
  }

  let site;
  try {
    site = await SiteService.getSite(rangeData.site.id);
  } catch(e) {
    return $q.reject({ message: 'Request for zoneId failed for the given site.' });
  }

  if (!site.zoneId) {
    return $q.reject({ message: 'Request for zoneId failed for the given site.' });
  }

  let data;
  try{ 
    data = getDayAheadData(site.zoneId, start, end);
  } catch(e){
    return $q.reject({ message: 'Request for cleared & forecasted data failed for the given site.' });
  }

  return handleBlockRange(rangeData, data[0].data, data[1].data);

}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download