Services

A controller's job is to wire a template to some data — it shouldn't also be the place where you fetch that data from a server or contain business logic that has nothing to do with the view. AngularJS's answer is the service: a plain object, shared across the whole app, that a controller can ask for by name.

$http: AngularJS's built-in AJAX service

$http is a service AngularJS provides out of the box for making requests. Like $scope, it's injected into your controller just by naming it as a parameter:

JS app.js
app.controller('UsersController', function($scope, $http) {
  $scope.users = [];

  $http.get('/api/users').then(function(response) {
    $scope.users = response.data;
  });
});
What happens
$http.get() sends a GET request to /api/users and returns a promise.
When the response arrives, .then()'s callback runs and assigns the parsed
JSON body to $scope.users — any ng-repeat bound to it re-renders automatically.

Notice that AngularJS is finding $http for you just because the controller function's parameter is named $http — this is dependency injection: you declare what you need by name, and AngularJS supplies it, rather than you importing or instantiating it yourself.

Writing a custom service

Once logic needs to be shared between more than one controller — formatting rules, cached data, anything that isn't view-specific — pulling it into a service keeps controllers small and that logic reusable:

JS cart-service.js
app.service('CartService', function() {
  var items = [];

  this.add = function(item) {
    items.push(item);
  };

  this.getTotal = function() {
    return items.reduce(function(sum, i) { return sum + i.price; }, 0);
  };
});

app.controller('CheckoutController', function($scope, CartService) {
  CartService.add({ name: 'Mug', price: 12 });
  CartService.add({ name: 'Notebook', price: 8 });
  $scope.total = CartService.getTotal();
});
Output
$scope.total is 20

CartService is requested by name in CheckoutController's parameter list, the same way $http was — any controller that lists CartService as a parameter gets access to exactly the same cart, not a fresh copy.

Services are singletons: AngularJS creates each service exactly once per app and hands the same instance to every controller that asks for it — that's precisely why CartService's items array stays populated across the whole application rather than resetting per controller. This is powerful (it's how you share state cleanly) and also a footgun: if a service holds data that should really be request-scoped or user-scoped, singleton state can leak between places you didn't intend, especially in a large app with many controllers touching the same service.