How to configure dependency injection in angularjs?

I'm a little confused about how the angularjs application works.

First of all, I have to say that I am a newbie user of angularjs , but I am familiar with other DI structures in other languages ​​(e.g. symfony in PHP, spring in Java, Unity bit).

Each of these DI implementations requires class definitions and a DI configuration .

Configuration usually includes:

  • how the class should be entered (automatically by name or type or manually)
  • if the container should return a singleton instance
  • what factory class should be used to create an object
  • serviceIds - each service can be restored by serviceId. This serviceId talks about the instance creation configuration (which services should be entered and which parameters should be used).
  • and etc.

And this configuration is missing in angularjs .

There is a dumb example of how I expect such a configuration to work. I have two services, each similar thing , but with a different implementation .

angular.module('notify', [], function($provide) { $provide.factory('LogNotifier', function($window) { return { messageMe: function(message) { $window.console.log(message); } } }); $provide.factory('AlertNotifier', function($window) { return { messageMe: function(message) { $window.alert(message); } } }); }); angular.module('myModule', ['notify'], function($provide) { // as notifier dependency I must specify its type. // is there any way how I would configure after its definition // which notifier implementation should be used? $provide.factory('DataLoader', function(AlertNotifier) { var loader = { loadAllItems: function() { AlertNotifier.messageMe('Loading items'); // let asume there is ajax call and promise object return return [ {name: 'Item1'}, {name: 'Item2'} ]; } } return loader; }); }); 

See http://jsfiddle.net/5ZDe6/1/

I want to switch between LogNotifier and AlertNotifier without changing the source code of the DataLoader service. Is it possible?

thanks

+4
source share
1 answer

A week later, playing with the angular, I realized one very important thing. All examples of angles have the DI configuration I was looking for. Configuration is the module definition itself .

All I had to do was define a separate module from the class definitions . Here the fiddle of my question is solved - http://jsfiddle.net/5ZDe6/7/

 /** * app module configuration */ angular.module('app', ['debug'], function($provide) { var dataLoaderFactory = function(Notifier) { return new my.model.DataLoader(Notifier); } // if you want to change notifier just change this injection to AlertNotifier dataLoaderFactory.$inject = ['LogNotifier']; // Specify factory with service ID DataLoader for class my.model.DataLoader $provide.factory('DataLoader', dataLoaderFactory); }) .controller('AppCtrl', my.controller.ItemCtrl); // you can even specify AppCtrl implementation (eg CachedCtrl) my.controller.ItemCtrl.$inject = ['$scope','DataLoader'] my.controller.CachedCtrl.$inject = ['$scope'] /** * debug module configuration */ angular.module('debug', [], function($provide) { $provide.factory('LogNotifier', function($window) { return new my.debug.LogNotifier($window); }); $provide.factory('AlertNotifier', function($window) { return new my.debug.AlertNotifier($window); }); }); 

And there are class definitions separate from the DI configuration.

 /** * Controller class definition */ my = window.my || {}; my.controller = my.controller || {}; my.controller.ItemCtrl = function($scope, loader) { $scope.items = loader.loadAllItems(); }; my.controller.CachedCtrl = function($scope) { $scope.items = [ { name: 'Cached ctrl value 1'}, { name: 'Cached ctrl value 2'} ] } /** * Model class definition */ my.model = my.model || {}; my.model.DataLoader = function(notifier) { this.notifier = notifier; this.loadAllItems = function() { this.notifier.messageMe('Loading items'); // let asume there is ajax call and promise object return return [ {name: 'Item1'}, {name: 'Item2'} ]; }; }; /** * Some debug classes definition */ my.debug = my.debug || {} my.debug.LogNotifier = function($window) { this.$window = $window; this.messageMe = function(message) { this.$window.console.log(message); } }; my.debug.AlertNotifier = function($window) { this.$window = $window; this.messageMe = function(message) { this.$window.alert(message); } } 

I believe this is the cleanest way to achieve my requirements. Unfortunately, if you really want to do this, you need to write a little more code .

Franc

+5
source

Source: https://habr.com/ru/post/1482533/


All Articles