In my opinions the main reasons are:
Persist and share data between Controllers.
I.E: You create a service that fetchs data form a database, if you store it inside a controller, once you change to another Controller the data will be discarded (unless you store it in the $rootScope but this is not the best way to do it) , but if you keep it inside a service (services are singletons), the data will persist when you change controllers.
Abstract data access logic by creating an API that will be used by your controllers/directives/services.
Keep business logic inside Controllers and data logic inside services.
DRY (Don't repeat yourself).
I.E: You have a series of functions that you need in different controllers, without the service you would have to repeat your code in each controller, with a service you can create a single API for this functions and inject it in every Controller/Directive/Service you need.
Here is an example:
var myApp = angular.module('myApp',[]);
//Here is the service Users with its functions and attributes
//You can inject it in any controller, service is a singleton and its data persist between controllers
myApp.factory('Users', function () {
//data logic
//fetch data from db and populate...
var name = "John";
var surname = "Doe"
function getName() { return name; }
function getFullName() { return name + ' ' + surname; }
function setName(newName) { name = newName; }
//API
return {
getName: getName,
getFullName: getFullName,
setName: setName
}
});
//An Util service with methods I will use in different controllers
myApp.factory('Util', function () {
//a bunch of useful functions I will need everywhere
function daysInMonth (month,year) {
return new Date(year, month+1,0).getDate();
}
return {
daysInMonth: daysInMonth
};
});
//Here I am injecting the User and Util services in the controllers
myApp.controller('MyCtrl1', ['$scope', 'Users', 'Util', function ($scope, Users, Util) {
$scope.user = Users.getFullName(); //"John Doe";
Users.setName('Bittle');
//Using Util service
$scope.days = Util.daysInMonth(05,2013);
}]);
myApp.controller('MyCtrl2', ['$scope', 'Users', 'Util', function ($scope, Users, Util) {
$scope.user = Users.getFullName(); //"Bittle Doe"; //The change that took place in MyCtrl1 hhas persisted.
}]);