Классы и внедрения зависимостей в 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)

0 ответов

Другие вопросы по тегам