Technically speaking, their declarations differ in the following way
var app = angular.module('app', [])
// Service - Constructor function(s) is instantiated at service declaration therefore one shared instance of the function
app.service('myService', function() {
this.myFunction = function() {
return {
"My message"
}
}
});
// Factory - Constructor function(s) is passed around in an object(can be used as a constuctor elsewhere e.g. new myFactory()) but there is still one shared instance of the factory.
app.factory('myFactory', function() {
return {
myMessage: "My message"
}
});
// Provider - Strictly uses the $get function as it's constructor function
app.provider('myProvider', function() {
var message = "My message"
return {
setAdditionalMessage: function(additionalMessage) {
message += " " + additionalMessage
},
$get: function() {
return {
myMessage: message
}
}
}
});
app.config(function(myProviderProvider) {
myProviderProvider.setAdditionalMessage("is a dope message"); // Introduces flexiblity since you can modify data before sharing to other modules
});
app.controller('app', function($scope, myService, myFactory, myProvider) {
// Usage
$scope.message = [ myService.myFunction, myFactory.myMessage, myProvider.myMessage ]; // Service and Factory return "My message" but Provider returns "My message is a dope message"
});
Services
are useful when designing simple applications where it's not necessary to be fluentFactories
are more powerful than services and allow you to use OOP principles better e.g. 'new' constructor, private functions/variablesProviders
are more flexible than Factories and Services. They allow you to modify data that is going to be shared to the app through modules before the modules are injected
There are 2 approaches to this, activate
and resolve
.
// activate
var app = angular.module('app');
app.controller('app', function($scope, someService) {
/**
* Function call that resolves route data in a promise
* Can be used with ng-view and a loading visual in the View
*/
activate();
function activate() {
return someService.getData().then(function(result){
$scope.data = result
return $scope.data
})
}
});
// resolve
app.config(function($routeProvider) {
$routeProvider.when('/someRoute', {
templateUrl: 'routeView.html',
controller: 'routeController',
resolve: {
someService: someService
}
})
});
app.service('someService', function($http) {
// A promise that resolves with data from an external api
this.getData: function() {
return $http.get('/api/endpoint')
.then(function(result) {
return result
})
.catch(function(error) {
console.log(error)
})
}
})
app.controller('routeController', function($scope, someService) {
/**
* Since the route definition couples this controller to the service in the config,
* the route will only transition to when the someService.getData() resolves.
* If it rejects then the route won't transition to at all
*/
$scope.data = someService.getData();
})
The main difference between activate
and resolve
is that activate
loads the view then binds data to the view after while resolve
waits for data before loading the view