Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This is in one of my AngularJS controllers:

websiteService.get('websites').then(function(data) {
    $scope.websites = data;
    websiteService.get('groups').then(function(data) {
        $scope.groups = data;
        websiteService.get('websites_groups').then(function(data) {
            $scope.websites_groups = data;
            // If everything goes well, my code will continue here - not really neat
        }, function(error) {
            $scope.errors.push(error);
        });
    }, function(error) {
        $scope.errors.push(error);
    });
}, function(error) {
    $scope.errors.push(error);
});

What would be a better, more elegant way to do this? Is there a best practice?

In my opinion, success functions are nested really nicely, in obvious and chronological and logical order, while error functions make everything messy.

share|improve this question
up vote 4 down vote accepted

If I understand correctly, you can unnest your code, and catch any possible error at the end. That's the idea of using promises:

websiteService.get('websites').then(function(data) {
  $scope.websites = data
  return websiteService.get('groups')
}).then(function(data) {
  $scope.groups = data
  return websiteService.get('websites_groups')
}).then(function(data) {
  $scope.websites_groups = data
}).catch(function(error) {
  $scope.errors.push(error)
})
share|improve this answer
    
Thanks a lot for this. One interesting thing that happens though - if an error occurs at first call, it doesn't get caught. For example if I modify 2nd or 3rd store name to something non-existent, $scope.errors variable will show it. If the first one is modified ('websites'), then just an error in console appears. Any idea why this would happen? – CodeVirtuoso May 14 '15 at 18:17

Define the error handler a little differently and make sure you provide it to each invocation of 'then' to handle a previous promise's errors.

var errorHandler = function(error) { 
  $scope.errors.push(error);
}

websiteService.get('websites')
.then(function(data) { 
    $scope.websites = data; 
    return websiteService.get('groups')
}, errorHandler)
.then(function(data) { 
    $scope.groups = data; 
    return websiteService.get('websites_groups')
}, errorHandler)
.then(function(data) { 
    $scope.websites_groups = data; 
}, errorHandler);

This pattern is particularly useful if you need the option of handling the error and then continuing the execution chain (accomplished by returning a resolved promise in the error handler).

By the way - I created a simple little test fiddle for experimenting with the effects of promises awhile back for my team. You can change which methods are rejected and resolved (and change which ones have handlers) to better understand the implications of each change. If it helps you can view it here.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.