1

I am writing an application in which I have to write a number of functions performing AJAX operations. I want to put all these functions under one service in a module and invoke these functions in the controllers whenever they are required. I know that it can be done using Angular JS modules, but not getting right approach to resolve it.

Can anyone help me with this? It would be great if you can demonstrate with an example.

S. Ravi Kiran
  • 4,053
  • 3
  • 21
  • 26

1 Answers1

2

I actually did a short blog entry on this a while ago.

Basic example:

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

//create a service:
app.factory('myService', function($http) {
   return {
      getFoo: function(success) {
        $http.get('/Foo/Url/Here').success(success);
      }
   }
});

//use it in a controller
app.controller('MyCtrl', function($scope, myService) {
    myService.getFoo(function(data) {
        $scope.foo = data;
    });
});

Example of using $http with $q for slicker results.

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

//create a service:
app.factory('myService', function($http, $q) {
   return {
      getFoo: function() {
          var deferred = $q.defer();
          $http.get('/Foo/Url/Here').success(function(data) {
              deferred.resolve(data);
          }).error(function(){
              deferred.reject();
          });
          return deferred.promise;
      }
   }
});

//use it in a controller
app.controller('MyCtrl', function($scope, myService) {
    $scope.foo = myService.getFoo();
});
Ben Lesh
  • 107,825
  • 47
  • 247
  • 232
  • 1
    In the second example, is there a reason you create a promise (`deferred`) instead of using the promise that $http returns? Also, do you have any thoughts about how the code could be modified so that the controller can know if there was an $http error (I think as written, $scope.foo will be empty if an error occurs, right)? – Mark Rajcok Feb 27 '13 at 17:30
  • +1 for that question... So it could be used as `$scope.foo = myService.getFoo()` and `foo` would only contain the data. Otherwise, `foo` would be an object with the ajax config, status *and* data on it. Personal preference I guess. Makes it cleaner when it's used. – Ben Lesh Feb 27 '13 at 18:58
  • Cleaner, okay, but it seems unable to handle errors. My current thinking is that the controller is the better place to deal with errors (and not the service), because we'll probably want to modify the view somehow to let the user know if $http failed. – Mark Rajcok Feb 27 '13 at 19:08
  • You can still handle errors. It returns a promise. So theoretically you could do `myService.getFoo().then()` with the proper callbacks, if you wanted to. My implementations tend to have some global error handling for HTTP errors that display in the same area, so individual error handling is less of an issue. – Ben Lesh Feb 27 '13 at 19:14
  • @MarkRajcok I would suggest that the service provide a way to register a function in case of error instead of exposing it's internals – Liviu T. Feb 27 '13 at 19:14
  • @LiviuT you could do that, but it wouldn't really fit with the rest of how everything works. You could also emit events for errors if you wanted to. In the end though, it's all up to the developer.. as long as it's 1. Maintainable, 2. Easy to follow and 3. testable. I don't see anything wrong with any implementation in this thread. – Ben Lesh Feb 27 '13 at 19:16
  • @blesh, thanks, I forgot that then() can be used on getFoo(). I would like more info about "global error handling... display in the same area" -- got a blog post? – Mark Rajcok Feb 27 '13 at 19:24
  • @MarkRajcok - I don't have anything handy atm, no. In my case I registered an interceptor and I'm populating an error message in $rootScope that displays on the page. – Ben Lesh Feb 27 '13 at 19:28