2013-04-17 6 views
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, которые можно было бы использовать вместо этого?

+0

Я думаю, что весь смысл объявления вашего пользовательского фабричного объекта внутри предоставляющей функции заключается в том, что он отвлекается от остальной части приложения. – Bart

+0

Если вам действительно нужна функция конструктора, то что вы делаете, это нормально! – ganaraj

+0

@ganaraj Причина, по которой мне «нужна», заключается в том, что ее потенциально можно повторно инициализировать несколько раз в контроллере в течение всего срока службы контроллера. Я мог бы просто вернуть обычный объект, а затем использовать метод init, но я не понимаю, как это будет лучше. Спасибо за ответ. – NilsH

ответ

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_ приложения (see documentation).

+0

Мы сражались честно ... Я теперь упаду на свой меч. –

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 

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

1

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

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

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"))) 

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

Смежные вопросы