Классы и внедрения зависимостей в Angular 1.x и EcmaScript 2015
Я использовал babel, gulp и browserify для создания своего приложения.
У меня есть простой контроллер, как это:
export default class MyCtrl() {
constructor() {
}
someMethod() {
// I know that this is not pure code, but it is not part of current question
return $http.post('/api/some/url/', {some: 'data'});
}
}
Проблема с внедрением зависимостей (DI). Это просто использовать 'ng-annotate' в конструкторе:
// @ngInject
constructor($http) {
// $http is resolved here
}
но не работает другими методами:
// @ngInject
someMethod($http) {
// FAIL. $http is resolved, because angular DI working only on main ctrl function
}
Я нашел 4 разных подхода к решению этой проблемы:
// 1, using this
constructor($http) {
this.http = $http;
}
someMethod() {
this.http.get(...);
}
// 2, using WeekMap
var deps = new WeekMap()
class MyCtrl {
constructor($http) {
deps.set(this, {http: $http)
}
someMethod() {
deps.get(this).http.get(...);
}
}
// 3, using inherited class
class Injectable {
constructor() {
var injector = angular.element(document).injector();
for (var prop in this) {
let fn = this[prop];
if(angular.isFunction(fn)) {
this[prop] = function(...args) {
injector.invoke(fn, this, args);
}
}
}
}
}
class MyCtrl extends Injectable {
constructor() {
super()
}
someMethod($http) {
$http.get(...)
}
// but then I can't use not injected values =(
//someAnotherMethod(valueFromCtrl, $http) {
//}
}
// 4, manually using injector
function di(...args) {
var injector = angular.element(document).injector()
if(args.length == 1) {
return injector.get(args[0])
}
var ret = args.map( name => injector.get(name) )
return args.length > 1 ? ret : ret[0];
}
class MyCtrl extends Injectable {
constructor() {
}
someMethod($http) {
var $http = di('$http');
$http.get(...)
}
}
Методы 1 и 2 требуют много кода для каждой зависимости. Метод 3 имеет проблему со значениями, передаваемыми в метод из контроллера. Я думаю, что лучший метод - это номер 4, но не уверен, что есть некоторые другие проблемы.
Вопрос в том, какой метод является более мощным? Есть ли лучшие практики для использования DI в суб-методах ES clasess?
// Методы UPD 1 и 2 требуют много дополнительного кода, например, для фабрик:
export default class SomeFactory {
constructor($http) {
this.$http = $http
}
getItems() {
this.$http.get('/').then(console.log.bind(console))
}
static makeFactory($http) {
return new SomeFactory($http)
}
}
angular.module('someModule', []).factory(SomeFactory.makeFactory)