I am me
I am me

Reputation: 131

Best separation of concerns approach for $http tasks between a controller and service

(working with Angular 1.5)

Read many articles (some recent, some old / outdated) on the subject of $http requests, promises, and separation of concerns, and am currently experimenting with the example below (Plunker here).

Was hoping to get some feedback on the following mental conundrum please:

With regards to the $http.get() request, have I done enough to ensure that concerns are separated between the controller and injected service?

I understand that it may not be the controllers responsibility to handle the error callback but I was thinking along the lines of: if a http error did occur (server down for example) then surely the controller would want to perform some contingency tasks e.g. cancel a loading spinner, redirect to an error page, etc.

Sorry if this question seems too generic - I hope the use-case below is acceptable.

( function () {

var app = angular.module('myApp', []);

app.service('userService', ['$http', '$q', function($http, $q) {

    this.getUsers = function(url){

        return $http.get(url).then(
            function(response) { // success
                return response.data;
            })['catch']( // error ('catch' workaround for IE8)
                function(response) {
                    return $q.reject(response);
                }
            );

    };

}]);

app.controller('usersCtrl', ['$scope', 'userService', function($scope, userService){

    $scope.getUsersData = function(url) {

        userService.getUsers(url).then(
            function(data){ // success - set $scope data, cancel spinner, etc
                console.log(data);
            },
            function(error){ // error - cancel spinner and display error messages, or possibly redirect to custom error page, etc
                console.log(error);
            }
        );

    };

    $scope.getUsersData('dummyData.htm');

}]);

}());

Upvotes: 1

Views: 113

Answers (2)

Daniel Bauer
Daniel Bauer

Reputation: 168

Looks like a good seperation of concerns. I did it exactly the way you described it in one of my projects :)

Questions: Why don't you set url directly in the getUsers function in the service? Does it change?

By the way: You can just return the promise from angular ..

    this.getUsers = function() {
       return $http.get(this.appConfig.baseApiUrl + "/users");
    };

... and use the success and error callbacks:

$scope.getUsersData = function() {    
        userService.getUsers().then(
           (function(response) { // success callback
                console.log(response.data);
            }),
           (function(error) { // error callback
                console.log(error);
            })
       );   
    };

You get the data from the response directly. And it looks much cleaner ;)

Upvotes: 1

MarcoS
MarcoS

Reputation: 17721

It is the controller's responsibility to handle the error callback from a service call (for example redirecting to some error page...).
Your use case example is perfect: the service just returns response.data in case of success or $q.reject(response) in case of errors, and the controllers handle success and error cases ...

Upvotes: 1

Related Questions