AngularJS: Когда использовать сервис вместо фабрики

278

Пожалуйста, несите меня здесь. Я знаю, что есть и другие ответы, такие как: AngularJS: Сервис против провайдера vs factory

Однако я все еще не могу понять, когда вы будете использовать службу через factory.

Из того, что я могу сказать, factory обычно используется для создания "общих" функций, которые могут вызываться несколькими контроллерами: Создание общих функций контроллера

Документы Angular, похоже, предпочитают factory через службу. Они даже ссылаются на "сервис", когда они используют factory, что еще более запутанно! http://docs.angularjs.org/guide/dev_guide.services.creating_services

Итак, когда вы будете использовать сервис?

Есть ли что-то, что возможно или намного проще с обслуживанием?

Есть ли что-то другое, что происходит за кулисами? Различия в производительности/памяти?

Вот пример. Помимо метода декларирования, они кажутся одинаковыми, и я не могу понять, почему я делаю одно против другого. http://jsfiddle.net/uEpkE/

Обновление: От ответа Томаса, похоже, подразумевается, что служба для более простой логики и factory для более сложной логики с частными методами, поэтому я обновил код скрипки ниже, и кажется, что оба могут поддерживать частные функции?

myApp.factory('fooFactory', function() {
    var fooVar;
    var addHi = function(foo){ fooVar = 'Hi '+foo; }

    return {
        setFoobar: function(foo){
            addHi(foo);
        },
        getFoobar:function(){
            return fooVar;
        }
    };
});
myApp.service('fooService', function() {
    var fooVar;
    var addHi = function(foo){ fooVar = 'Hi '+foo;}

    this.setFoobar = function(foo){
        addHi(foo);
    }
    this.getFoobar = function(){
        return fooVar;
    }
});

function MyCtrl($scope, fooService, fooFactory) {
    fooFactory.setFoobar("fooFactory");
    fooService.setFoobar("fooService");
    //foobars = "Hi fooFactory, Hi fooService"
    $scope.foobars = [
        fooFactory.getFoobar(),
        fooService.getFoobar()
    ];
}
  • 0
    Конечно, сервис поддерживает private, но если вы правильно прочитали мой пост, это чисто кодовый стиль: мы также можем воспользоваться новой лексической областью для симуляции «приватных» переменных. Это "SIMULATE"
  • 0
    Я считаю это обсуждение очень полезным stackoverflow.com/questions/15666048/…
Показать ещё 1 комментарий
Теги:
angularjs-service
angularjs-factory

8 ответов

265
Лучший ответ

Описание

У вас здесь разные вещи:

Сначала:

  • Если вы используете службу, вы получите экземпляр функции ( "this" ключевое слово).
  • Если вы используете factory, вы получите значение, которое возвращается вызывая ссылку на функцию (оператор return в factory).

ref: angular.service vs angular.factory

Второй:

Имейте в виду, что все провайдеры в AngularJS (стоимость, постоянная, услуги, фабрики) являются синглтонами!

Третий:

Использование одного или другого (службы или factory) относится к стилю кода. Но общий способ в AngularJS состоит в использовании factory.

Почему?

Потому что "Метод factory является наиболее распространенным способом получения объектов в системе встраивания зависимостей AngularJS. Он очень гибкий и может содержать сложную логику создания. Поскольку фабрики являются регулярными функциями, мы можем также использовать новую лексическую область для моделирования переменных "private". Это очень полезно, поскольку мы можем скрыть детали реализации данной службы".

(ref: http://www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821).


Использование

Сервис: может быть полезно для совместного использования служебных функций, которые полезны для вызова, просто добавляя () к ссылке с введенной функцией. Также может выполняться с injectedArg.call(this) или аналогичным.

Factory: Может быть полезно вернуть функцию класса, которая затем может быть новой для создания экземпляров.

Итак, используйте factory, когда у вас сложная логика в вашей службе, а вы не хотите раскрывать эту сложность.

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

Но вы увидите со временем, что будете использовать factory в 80% случаев, я думаю.

Подробнее: http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


ОБНОВЛЕНИЕ:

Отличный пост здесь: http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html

"Если вы хотите, чтобы ваша функция вызывалась как обычная функция, используйте factory. Если вы хотите, чтобы ваша функция была создана с новым оператор, используйте сервис. Если вы не знаете разницы, используйте factory."


ОБНОВЛЕНИЕ:

Команда AngularJS выполняет свою работу и дает объяснение: http://docs.angularjs.org/guide/providers

И с этой страницы:

"Factory и Service являются наиболее часто используемыми рецептами. Единственное различие между ними заключается в том, что рецепт службы лучше работает для объектов пользовательского типа, а factory может создавать примитивы и функции JavaScript.

  • 6
    Re First: я читаю это везде, но я не понимаю практических последствий этого. Я думаю, из вашего ответа нет практической разницы "по большей части"? Спасибо за книгу ref хотя!
  • 0
    Это просто, если ваш сервис действительно сложный и вам нужны частные методы и объекты, использующие фабрику
Показать ещё 5 комментариев
98

allernhwkim изначально отправил ответ по этому вопросу, ссылаясь на его блог, однако модератор удалил его. Это единственное сообщение, которое я нашел, который не просто говорит вам, как делать то же самое с сервисом, провайдером и factory, но также сообщает вам, что вы можете делать с провайдером, которого вы не можете с помощью factory и с помощью factory, который вы не можете использовать со службой.

Непосредственно из своего блога:

app.service('CarService', function() {
   this.dealer="Bad";
    this.numCylinder = 4;
});

app.factory('CarFactory', function() {
    return function(numCylinder) {
      this.dealer="Bad";
        this.numCylinder = numCylinder
    };
});

app.provider('CarProvider', function() {
    this.dealerName = 'Bad';
    this.$get = function() {
        return function(numCylinder) {
            this.numCylinder = numCylinder;
            this.dealer = this.dealerName;
        }
    };
    this.setDealerName = function(str) {
      this.dealerName = str;
    }      
});

Это показывает, как CarService всегда будет производить автомобиль с 4 цилиндрами, вы не сможете его изменить для отдельных автомобилей. В то время как CarFactory возвращает функцию, поэтому вы можете сделать new CarFactory в своем контроллере, пройдя несколько цилиндров, характерных для этого автомобиля. Вы не можете сделать new CarService, потому что CarService - это объект, а не функция.

Причина, по которой фабрики работают не так:

app.factory('CarFactory', function(numCylinder) {
      this.dealer="Bad";
      this.numCylinder = numCylinder
});

И автоматически возвращайте функцию для создания экземпляра, потому что тогда вы не можете этого сделать (добавьте вещи в прототип /etc ):

app.factory('CarFactory', function() {
    function Car(numCylinder) {
        this.dealer="Bad";
        this.numCylinder = numCylinder
    };
    Car.prototype.breakCylinder = function() {
        this.numCylinder -= 1;
    };
    return Car;
});

Посмотрите, как буквально factory создает автомобиль.

Вывод из его блога довольно хорош:

В заключение,

---------------------------------------------------  
| Type    | Singleton| Instantiable | Configurable|
---------------------------------------------------  
| Factory | Yes      | No           | No          |
---------------------------------------------------  
| Service | Yes      | Yes          | No          |
---------------------------------------------------  
| Provider| Yes      | Yes          | Yes         |       
---------------------------------------------------  
  • Используйте factory, когда вам нужен простой объект, такой как Hash, для example {foo; 1, bar: 2} Его легко закодировать, но вы не можете создать экземпляр он.

  • Используйте службу, когда вам нужно создать экземпляр объекта, т.е. новый Клиент(), новый комментарий() и т.д.

  • Используйте Provider, когда вам нужно его настроить. то есть тестовый URL, URL-адрес QA, производственный адрес.

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

Не делайте этого:

app.factory('CarFactory', function() {
    return {
        numCylinder: 4
    };
});

Используйте сервис вместо:

app.service('CarService', function() {
    this.numCylinder = 4;
});
  • 11
    это очень полезно для меня. +1 для сравнительной таблицы
  • 5
    если вы определяете сервисную функцию с одним параметром numCylinder, тогда она будет иметь ту же гибкость, что и фабричный метод
Показать ещё 9 комментариев
19

Концепция для всех этих поставщиков намного проще, чем первоначально. Если вы проанализируете поставщика и вытащите разные части, он станет очень понятным.

Проще говоря, каждый из этих поставщиков является специализированной версией другой, в следующем порядке: provider > factory > value/constant/service.

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

Это изображение иллюстрирует, что я имею в виду. На этом изображении вы увидите код для провайдера, с выделенными фрагментами, показывающими, какие части поставщика могут использоваться для создания factory, значения и т.д. вместо.

Поставщики AngularJS, заводы, сервисы и т.д. - это одно и то же: http://www.simplygoodcode.com/wp-content/uploads/2015/11/angularjs-provider- сервис- factory -highlight.png

Для получения более подробной информации и примеров из сообщения в блоге, где я получил изображение, перейдите по ссылке: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

8

Оба factory и службы приводят к одноточечным объектам, которые могут быть настроены поставщиками и введены в контроллеры и блоки запуска. С точки зрения инъектора, нет никакой разницы, был ли объект получен из factory или службы.

Итак, когда использовать factory и когда использовать услугу? Это сводится к вашим предпочтениям в кодировании, и ничего больше. Если вам нравится модульный шаблон JS, перейдите к factory. Если вам нравится стиль конструктора ( "класс" ), перейдите к службе. Обратите внимание, что оба стиля поддерживают частные члены.

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

  • 0
    Не могли бы вы привести пример того, что вы подразумеваете под предоставлением различных параметров конструктору в блоке конфигурации? Как вы предоставляете параметры, если это просто сервис или фабрика. Что вы подразумеваете под «совместно с провайдером»? Возможность его настройки заставляет меня думать, что многие из моих объектов должны быть провайдерами или фабриками или службами.
2

Даже когда говорят, что все сервисы и заводы однотонные, я не согласен с этим на 100 процентов. Я бы сказал, что фабрики не одиночные, и это точка моего ответа. Я бы действительно подумал о имени, которое определяет каждый компонент (Service/ Factory), я имею в виду:

A factory, потому что он не является одиночным, вы можете создавать столько, сколько хотите, когда вы вводите, поэтому он работает как объект factory. Вы можете создать factory объекта вашего домена и работать более комфортно с этими объектами, которые могут быть похожими на объект вашей модели. Когда вы извлекаете несколько объектов, вы можете отображать их в этих объектах, и они могут действовать как другой слой между DDBB и моделью AngularJs. Вы можете добавлять методы к объектам, чтобы вы ориентировались на объекты немного больше вашего приложения AngularJs.

Между тем служба - это одиночный элемент, поэтому мы можем создать только один вид, возможно, не создадим, но у нас есть только один экземпляр, когда мы вводим в контроллер, поэтому служба больше похожа на общая служба (вызовы отдыха, функциональность..) для контроллеров.

Концептуально вы можете думать, что службы предоставляют услугу, фабрики могут создавать несколько экземпляров (объектов) класса

2

Нет ничего, что Factory не может сделать или лучше по сравнению с Сервисом. И наоборот. Factory просто кажется более популярным. Причиной этого является его удобство в обращении с частными/общественными членами. Служба будет более неуклюжей в этом отношении. При кодировании службы вы, как правило, делаете своих членов объектов общедоступными с помощью ключевого слова "this" и можете внезапно обнаружить, что эти публичные элементы не видны частным методам (т.е. Внутренним функциям).

var Service = function(){

  //public
  this.age = 13;

  //private
  function getAge(){

    return this.age; //private does not see public

  }

  console.log("age: " + getAge());

};

var s = new Service(); //prints 'age: undefined'

Angular использует ключевое слово "новое" для создания службы для вас, поэтому экземпляр Angular переходит к контроллеру, будет иметь тот же недостаток. Конечно, вы можете преодолеть проблему, используя это/это:

var Service = function(){

  var that = this;

  //public
  this.age = 13;

  //private
  function getAge(){

    return that.age;

  }

  console.log("age: " + getAge());

};

var s = new Service();// prints 'age: 13'  

Но с большой константой Сервиса это сделает код плохо читаемым. Более того, прототипы службы не будут видеть частных членов - для них будет доступна только публика:

var Service = function(){

  var name = "George";

};

Service.prototype.getName = function(){

  return this.name; //will not see a private member

};

var s = new Service();
console.log("name: " + s.getName());//prints 'name: undefined'

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

  • 0
    Этот ответ имеет несколько проблем. Во-первых, этот пост демонстрирует концепцию лексического анализа в Javascript, а не то, как работают сервисы AngularJS. Во-вторых, контекст вызова myapp.service(...) полностью отсутствует. Где должен вызываться new Service() , в сервисной функции или в месте, где вводится Service. Третий листинг просто невозможен в контексте myapp.service ('Service', function() {...}) .
0

Можно использовать способ: создать объект или j ust для доступа к функциям из


Вы можете создать новый объект из службы

app.service('carservice', function() {
    this.model = function(){
        this.name = Math.random(22222);
        this.price = 1000;
        this.colour = 'green';
        this.manufacturer = 'bmw';
    }
});

.controller('carcontroller', function ($scope,carservice) { 
    $scope = new carservice.model();
})

Примечание:

  • Служба
  • по умолчанию возвращает объект, а не функцию конструктора.
  • Итак, почему для функции конструктора установлено значение this.model.
  • Благодаря этой службе будет возвращен объект, но но внутри этого объекта будет функция-конструктор, которая будет использоваться для создания нового объекта;

Вы можете создать новый объект из factory

app.factory('carfactory', function() {
    var model = function(){
        this.name = Math.random(22222);
        this.price = 1000;
        this.colour = 'green';
        this.manufacturer = 'bmw';
    }
    return model;
});

.controller('carcontroller', function ($scope,carfactory) { 
    $scope = new carfactory();
})

Примечание:

  • factory по умолчанию возвращает конструктор, а не объект.
  • Итак, почему новый объект может быть создан с помощью функции-конструктора.

Создать сервис для простого доступа к простым функциям

app.service('carservice', function () {
   this.createCar = function () {
       console.log('createCar');
   };
   this.deleteCar = function () {
       console.log('deleteCar');
   };
});

.controller('MyService', function ($scope,carservice) { 
    carservice.createCar()
})

Создать factory для простого доступа к простым функциям

app.factory('carfactory', function () {
    var obj = {} 
        obj.createCar = function () {
            console.log('createCar');
        };
       obj.deleteCar = function () {
       console.log('deleteCar');
    };
});

.controller('MyService', function ($scope,carfactory) { 
    carfactory.createCar()
})

Заключение:

  • вы можете использовать способ, которым хотите, создавать ли новый объект или просто для доступа к простым функциям
  • Не будет никакого удара по производительности, используя один над другим
  • Оба являются одноэлементными объектами, и для каждого приложения создается только один экземпляр.
  • Быть только одним экземпляром, где передается их ссылка.
  • В angular документация factory называется службой, а также служба называется службой.
0

Услуги

Синтаксис: module.service('serviceName', function); Результат. При объявлении serviceName в качестве аргумента для инъекции вам будет предоставлен фактический справочник функций, переданный модулю service.service.

Использование. Может быть полезно для совместного использования служебных функций, которые полезны для вызова, просто добавляя() к ссылке с введенной функцией. Также можно запустить с помощью injectedArg.call(this) или аналогичного.

Заводы

Синтаксис: module.factory('factoryName', function);

Результат: при объявлении имени factoryName в качестве аргумента для инъекции вам будет предоставлено значение, возвращаемое вызовом ссылки на функцию, переданной модулю .factory.

Использование. Может оказаться полезным для возврата функции класса, которая затем может быть создана для создания экземпляров.

Провайдеры

Синтаксис: module.provider('providerName', function);

Результат. При объявлении имени поставщика в качестве аргумента для инъекции вам будет предоставлено значение, возвращаемое при вызове метода $get ссылки на функцию, переданной модулю .provider.

Использование. Может оказаться полезным для возврата функции класса, которая затем может быть создана для создания экземпляров, но перед введением требуется какая-то конфигурация. Возможно, полезно для классов, которые многократно используются для разных проектов? Еще один туманный на этом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню