AngularJS Dependency Injection


What is Dependency Injection

The explanation on Wikipedia is: Dependency Injection (DI) is a software design pattern in which one or more dependencies (or services) are injected (or passed by reference) into an independent object (or client), and then become part of that client's state.

This pattern separates the creation of a client's dependencies from its own behavior, which makes the program design loosely coupled and follows the dependency inversion and single responsibility principles. In direct contrast to the service locator pattern, it allows the client to know how the client uses the system to find dependencies.

In one sentence — If there's nothing, don't come to me; if there's something, I'll come to you.

AngularJS provides a very good dependency injection mechanism. The following 5 core components are used for dependency injection:

  • value
  • factory
  • service
  • provider
  • constant

value

Value is a simple JavaScript object used to pass values to controllers (configuration phase):

// 定义一个模块
var mainApp = angular.module("mainApp", []);

// 创建 value 对象 "defaultInput" 并传递数据
mainApp.value("defaultInput", 5);
...

// 将 "defaultInput" 注入到控制器
mainApp.controller('CalcController', function($scope, CalcService, defaultInput) {
   $scope.number = defaultInput;
   $scope.result = CalcService.square($scope.number);
   
   $scope.square = function() {
      $scope.result = CalcService.square($scope.number);
   }
});

factory

factory is a function used to return a value. It is created when service and controller need it.

Usually we use factory functions to calculate or return values.

// 定义一个模块
var mainApp = angular.module("mainApp", []);

// 创建 factory "MathService" 用于两数的乘积 provides a method multiply to return multiplication of two numbers
mainApp.factory('MathService', function() {
   var factory = {};
   
   factory.multiply = function(a, b) {
      return a * b
   }
   return factory;
}); 

// 在 service 中注入 factory "MathService"
mainApp.service('CalcService', function(MathService){
   this.square = function(a) {
      return MathService.multiply(a,a);
   }
});
...

provider

In AngularJS, a service, factory, etc. is created through a provider (configuration phase).

Provider provides a factory method get(), which is used to return value/service/factory.

// 定义一个模块
var mainApp = angular.module("mainApp", []);
...

// 使用 provider 创建 service 定义一个方法用于计算两数乘积
mainApp.config(function($provide) {
   $provide.provider('MathService', function() {
      this.$get = function() {
         var factory = {};  
         
         factory.multiply = function(a, b) {
            return a * b; 
         }
         return factory;
      };
   });
});

constant

constant is used to pass values in the configuration phase. Note that this constant is not available in the configuration phase.

mainApp.constant("configParam", "constant value");

Examples

The following examples demonstrate the dependency injection mechanisms mentioned above.

AngularJS Example - factory

var mainApp = angular.module("mainApp", []); mainApp.value("defaultInput", 5); mainApp.factory('MathService', function() { var factory = {}; factory.multiply = function(a, b) { return a * b; } return factory; }); mainApp.service('CalcService', function(MathService){ this.square = function(a) { return MathService.multiply(a,a); } }); mainApp.controller('CalcController', function($scope, CalcService, defaultInput) { $scope.number = defaultInput; $scope.result = CalcService.square($scope.number); $scope.square = function() { $scope.result = CalcService.square($scope.number); } });

Try it Yourself »

AngularJS Example - provider

var mainApp = angular.module("mainApp", []); mainApp.config(function($provide) { $provide.provider('MathService', function() { this.$get = function() { var factory = {}; factory.multiply = function(a, b) { return a * b; } return factory; }; }); }); mainApp.value("defaultInput", 5); mainApp.service('CalcService', function(MathService){ this.square = function(a) { return MathService.multiply(a,a); } }); mainApp.controller('CalcController', function($scope, CalcService, defaultInput) { $scope.number = defaultInput; $scope.result = CalcService.square($scope.number); $scope.square = function() { $scope.result = CalcService.square($scope.number); } });

Try it Yourself »
Other extensions