Создать класс инъекции (конструктор)

17

Я новичок в AngularJS, и я только начинаю понимать понятия и различия factory , service и controller . Насколько я понимаю, factory используется для возврата «объекта значения», который может быть введен. Большинство примеров, которые я видел, делают примерно так:

angular.module('module.factories', function() {
    factory('FactoryObject', function() {
        return {
            someFunction: function(someParam) {};
            someOtherFunction: function(someOtherParam) {});
        };
    });
});

В моем controller , я хочу, чтобы иметь возможность использовать этот объект, но я хотел бы инициализировать / инстанцировать его в контроллере, так как он может быть повторно инициализирован в зависимости от событий / действий в контроллере. Поэтому мне было интересно, могу ли я вернуть функцию-конструктор на фабрике?

angular.module('module.factories', function() {
    factory('FactoryObject', function() {

        function FactoryObject(initParam) {
        }

        FactoryObject.prototype.someFunction = function() {};

        return FactoryObject;

    });
});

Является ли это подходящей моделью для угловой фабрики? Или это просто «overkill», чтобы использовать фабрику для пользовательского объекта, подобного этому? Должен ли я просто включить его в файл js библиотеки и вместо этого ссылаться на него? Одно из преимуществ его установки на заводе заключается в том, что будет легко издеваться над ним в тесте, поскольку оно будет введено там, где оно используется. Существуют ли какие-либо другие механизмы в Angular, которые могут быть использованы вместо этого?

    
задан NilsH 17.04.2013 в 08:01
источник
  • Я думаю, что весь смысл объявления вашего пользовательского фабричного объекта внутри предоставляющей функции заключается в том, что он абстрагируется от остальной части приложения. –  Bart 17.04.2013 в 08:49
  • Если вам действительно нужна функция конструктора, то то, что вы делаете, прекрасно! –  ganaraj 17.04.2013 в 10:48
  • @ganaraj Причина, по которой мне «нужна», состоит в том, что ее потенциально можно повторно инициализировать несколько раз в контроллере в течение всего срока службы контроллера. Я мог бы просто вернуть обычный объект, а затем применить метод init, но я не понимаю, как это будет лучше. Спасибо за ответ. –  NilsH 17.04.2013 в 11:11
  • Если вы ищете тот же объект для повторной инициализации, то передача конструктора не будет решением. Если вы хотите иметь возможность создавать несколько объектов типа (конструкторская функция), то это будет правильным решением. –  ganaraj 17.04.2013 в 11:13
  • @ganaraj Нет, я действительно ищу новые экземпляры, поэтому я использую новый FactoryObject (initParam) в контроллере. Другим примером было то, как я мог бы решить это иначе. –  NilsH 17.04.2013 в 11:16

4 ответа

3

Вы совершенно правы, это способ создания инъекционных «классов» (конструкторов). Однако использование factory необходимо только тогда, когда вам нужно вводить другие вещи, которые будут использоваться вашим классом:

.factory('Class', ['$q', function ($q) {
    function Class () {}
    Class.prototype = {
        constructor: Class,
        doSomeAsyncAction: function () {
            return $q(function (resolve, reject) {
                // ...
            });
        },
        // ...
    };
    return Class;
})

Если вы создаете полностью независимый класс (например, некоторую структуру данных), вы можете просто использовать constant , чтобы ваш класс был доступен даже у поставщиков услуг:

(function (undefined) {
    function Class () {}
    Class.prototype = { ... };
    angular.module(...)
        .constant('Class', Class);
})();

В качестве побочного элемента использование provider не поможет вам в этом. Провайдеры выполняют совершенно другую цель и (помимо прочего) возвращают заводскую функцию, которая затем используется _once_ в первой запрошенной инъекции для создания одного экземпляра службы. Провайдеры используются для настройки этого экземпляра единой службы в фазе _config_ построения приложения ( см. Документацию ).

    
ответ дан hon2a 18.12.2014 в 07:19
  • Мы сражались честно ... Я теперь упаду на свой меч. –  Brian Vanderbusch 18.12.2014 в 13:43
8

У меня такая же проблема. Вот что я реализовал:

angular.module('foo', [])
.factory('Foo', ['$http', function($http) {
  return function(a, b) {
    this.arr = [];
    this.a = a;
    this.b = b;
    this.random = Math.floor(Math.random()*11);

    this.someFunc = function(c) {
      this.arr.push(c);
    };
  };
}]);

Теперь я могу сделать:

var f1 = new Foo('A', 'B');
f1.random;  // i.e. 0
f1.someFunc('z');  // only affects f1.arr
var f2 = new Foo('C', 'D');
f2.random;  // i.e. 8
f2.someFunc('y');  // only affects f2.arr

Делает вещи более модульными. Надеюсь, что это поможет.

    
ответ дан Foo L 14.06.2013 в 02:07
1

У меня был тот же вопрос. Я нашел потрясающую статью о том, как настроить Object-oriented AngularJS Services. Вот статья . Обратите внимание на примечание об использовании заводов, а не услуг. Он также охватывает расширение ваших объектов. Я нашел его очень простым в настройке, и он идеально вписывается в Angular, сохраняя Javascript простым и прямым.

Для служб Factory, которые являются одноточечными и не нуждаются в создании экземпляров, я использую подход объектного литерала, который имеет некоторые преимущества производительности.

    
ответ дан Darryl 18.12.2014 в 07:05
1

Вот как я решил проблему:

(function (myModule) {
    'use strict';

    myModule.service('myService', [
        function() {
            var serivce = this;
            var obj = null;

            service.func1 = function(a, b) {

            }

            service.func2 = function(c, d) {
                . . .
                return something;
            }

            var constructor = function(myObj) {
                obj = myObj;

                return service;
            }

            return constructor;
        }
    ]);
}(angular.module("myModule")))

(function(myModule) {
    'use strict';

    myModule.controller('myController', [
        '$scope', 'myService', function($scope, myService) {

            var service = myService($scope.someObj);

            $scope.someOtherObj = service.func2($scope.a, $scope.b);

        }
    ]);
}(angular.module("myModule")))

Единственное, что возвращается службой, это конструктор, а затем служба возвращает остальную часть службы.

    
ответ дан jolySoft 22.02.2016 в 19:33