Смущенный о Сервисе против Фабрики

562

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

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

Пример кода для демонстрации:

var factories = angular.module('app.factories', []);
var app = angular.module('app',  ['ngResource', 'app.factories']);

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

При изменении user.first в ACtrl получается, что user.first в BCtrl также изменяется, например. User - одноэлементный?

Мое предположение заключалось в том, что новый экземпляр был введен в контроллер с помощью factory?

Теги:

22 ответа

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

Все службы angular - это синглтоны:

Документы (см. Услуги как одиночные точки): https://docs.angularjs.org/guide/services

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

В основном разница между сервисом и factory выглядит следующим образом:

app.service('myService', function() {

  // service is just a constructor function
  // that will be called with 'new'

  this.sayHello = function(name) {
     return "Hi " + name + "!";
  };
});

app.factory('myFactory', function() {

  // factory returns an object
  // you can run some code before

  return {
    sayHello : function(name) {
      return "Hi " + name + "!";
    }
  }
});

Ознакомьтесь с этой презентацией о $provision: http://slides.wesalvaro.com/20121113/#/

Эти слайды использовались в одном из сообществ AngularJs: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html

  • 13
    См. Также stackoverflow.com/questions/15666048/…, где обсуждаются различия между обслуживанием, фабрикой и предоставлением.
  • 31
    Официальный документ косвенно [так! не достаточно ясно] подразумевает, что даже если вы определяете сервис с фабрикой, он создается только один раз. Другими словами, он НЕ создается снова согласно ссылке (точке внедрения) - как бы вы это ни называли. Оба способа приводят к одному экземпляру на инжектор.
Показать ещё 12 комментариев
330

Для меня было откровение, когда я понял, что все они работают одинаково: запустив что-то один раз, сохранив полученное значение, а затем кашляйте то же самое сохраненное значение при ссылке через Injection Dependency.

Скажем, что у нас есть:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

Разница между тремя заключается в следующем:

  • a сохраненное значение происходит от запуска fn, другими словами: fn()
  • b s сохраненное значение происходит от new ing fn, другими словами: new fn()
  • c s сохраненное значение происходит от первого получения экземпляра с помощью new ing fn, а затем запускает метод $get экземпляра

что означает, что-то вроде объекта кэша внутри angular, значение которого для каждой инъекции назначается только один раз, когда они были введены в первый раз и где:

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()

Вот почему мы используем this в сервисах и определяем this.$get у поставщиков.

Надеюсь, что это поможет.

  • 54
    наконец, вменяемое объяснение. Angular безумен и настолько ужасен, что причиняет боль.
  • 8
    Это должен быть принятый ответ, поскольку он фактически отвечает на вопрос, ПОЧЕМУ фабрики, службы и поставщики возвращают одноэлементные значения. Другие ответы объясняют разницу между фабриками, службами и поставщиками, но никогда не касаются одноэлементного аспекта.
Показать ещё 7 комментариев
89

живой пример

Пример "привет мир"

с factory/service/provider:

var myApp = angular.module('myApp', []);

//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!"
    };
});

//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!"
        }
    };
});

//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {
    // In the provider function, you cannot inject any
    // service or factory. This can only be done at the
    // "$get" method.

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!"
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});


function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {

    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}​
58

Существует также способ вернуть конструктор, чтобы вы могли возвращать классы newable на фабриках, например:

function MyObjectWithParam($rootScope, name) {
  this.$rootScope = $rootScope;
  this.name = name;
}
MyObjectWithParam.prototype.getText = function () {
  return this.name;
};

App.factory('MyObjectWithParam', function ($injector) {
  return function(name) { 
    return $injector.instantiate(MyObjectWithParam,{ name: name });
  };
}); 

Итак, вы можете сделать это в контроллере, который использует MyObjectWithParam:

var obj = new MyObjectWithParam("hello"),

См. полный пример:
http://plnkr.co/edit/GKnhIN?p=preview

И вот страницы группы google, где обсуждалось:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ

  • 0
    У меня проблемы с минификацией на вашем примере. Вы знаете, как я должен аннотировать это?
  • 2
    Да, там существует сокращенная запись для Angular. Должно быть что-то вроде этого: App.factory('MyObjectWithParam', ['$injector', function ($injector) { return function(name) { return $injector.instantiate(MyObjectWithParam,{ name: name }); }; }]); Подробнее об этом читайте здесь: docs.angularjs.org/tutorial/step_05
Показать ещё 3 комментария
52

Вот основные отличия:

Услуги

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

Результат: при объявлении serviceName как аргумент для инъекции вам будет предоставлен экземпляр функции, переданный в module.service.

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

Заводы

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

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

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

Также проверьте Документацию AngularJS и аналогичный вопрос о stackoverflow запутался в службе vs factory.

Вот пример использования служб и factory. Подробнее о Служба AngularJS vs factory.

  • 4
    Одно из более понятных описаний!
  • 6
    Это имеет смысл для меня. Фабрика he возвращает план создания новых объектов.
26

Добавляя к первому ответу, я думаю, что .service() предназначен для людей, которые написали свой код в более объектно-ориентированном стиле (С#/Java) (используя это ключевое слово и экземпляр объекта через функцию prototype/Constructor).

Factory предназначен для разработчиков, которые пишут код, более естественный для javascript/функционального стиля кодирования.

Взгляните на исходный код метода .service и .factory внутри angular.js - внутренне они все вызывают метод провайдера:

  function provider(name, provider_) {
    if (isFunction(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
  }

  function factory(name, factoryFn) { \
    return provider(name, { $get: factoryFn }); 
  }

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }
23

Очень просто:

.service - зарегистрированная функция будет вызываться как конструктор (aka 'newed')

.factory - зарегистрированная функция будет вызываться как простая функция

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

  • 6
    да. давайте не будем усложнять вещи, чем они есть на самом деле
19

Все провайдеры работают одинаково. Различные методы service, factory, provider позволяют просто сделать то же самое в меньшем количестве кода.

P.S. Там также value и constant.

В каждом специальном случае цепочка, начинающаяся с provider и заканчивающаяся на value, имеет дополнительное ограничение. Поэтому, чтобы решить между ними, вы должны спросить себя, что позволит вам выполнить то, что вы хотите, с меньшим количеством кода.

Вот фотография, которая показывает вам, что я имею в виду:

Изображение 3630

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

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

  • 0
    Службы называются одноэлементными, но почему они одноэлементные, если каждый раз, когда я внедряю их, создается новый экземпляр?
  • 1
    @AnkurMarwaha Новый экземпляр создается не каждый раз, он создается только один раз и кэшируется AngularJS. Это верно, используете ли вы провайдера, фабрику, сервис и т. Д. Вы можете подтвердить это с помощью console.log() и внедрить в несколько контроллеров.
Показать ещё 4 комментария
13

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

Основные примеры

Возвращает объект класса, который имеет один метод

Вот сервис, который имеет один метод:

angular.service('Hello', function () {
  this.sayHello = function () { /* ... */ };
});

Вот factory, который возвращает объект с помощью метода:

angular.factory('ClassFactory', function () {
  return {
    sayHello: function () { /* ... */ }
  };
});

Возвращает значение

A factory, который возвращает список чисел:

angular.factory('NumberListFactory', function () {
  return [1, 2, 3, 4, 5];
});

console.log(NumberListFactory);

Служба, которая возвращает список номеров:

angular.service('NumberLister', function () {
  this.numbers = [1, 2, 3, 4, 5];
});

console.log(NumberLister.numbers);

Выход в обоих случаях одинаковый, список номеров.

Расширенные примеры

Переменные класса с использованием заводов

В этом примере мы определяем CounterFactory, он увеличивает или уменьшает счетчик, и вы можете получить текущий счетчик или узнать, сколько объектов CounterFactory было создано:

angular.factory('CounterFactory', function () {
  var number_of_counter_factories = 0; // class variable

  return function () {
    var count = 0; // instance variable
    number_of_counter_factories += 1; // increment the class variable

    // this method accesses the class variable
    this.getNumberOfCounterFactories = function () {
      return number_of_counter_factories;
    };

    this.inc = function () {
      count += 1;
    };
    this.dec = function () {
      count -= 1;
    };
    this.getCount = function () {
      return count;
    };
  }

})

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

var people_counter;
var places_counter;

people_counter = new CounterFactory();
console.log('people', people_counter.getCount());
people_counter.inc();
console.log('people', people_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());

places_counter = new CounterFactory();
console.log('places', places_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());
console.log('counters', places_counter.getNumberOfCounterFactories());

Вывод этого кода:

people 0
people 1
counters 1
places 0
counters 2
counters 2
  • 0
    это полезный пример, number_of_counter_factories похож на мета-атрибут класса CounterFactory, верно? Я понимаю, что этот пример можно реплицировать на службу (скажите, если я ошибаюсь), в чем будет семантическая разница в этом случае?
  • 0
    Полезный пример! Так что это в основном означает, что на фабрике у вас может быть тот дополнительный уровень абстракции, который бы не попал в сервис. Что бы ни возвращалось, новый экземпляр этого будет возвращаться всякий раз, когда используется «новый». Любые переменные, которые не объявлены внутри возвращаемого блока, будут одиночными. Я правильно понял?
Показать ещё 1 комментарий
12

"Factory" и "Service" - это разные способы выполнения DI (инъекция зависимостей) в angular.

Итак, когда мы определяем DI, используя "сервис", как показано в приведенном ниже коде. Это создает новый GLOBAL-экземпляр объекта "Logger" и вводит его в функцию.

app.service("Logger", Logger); // Injects a global object

Когда вы определяете DI с помощью "Factory" , он не создает экземпляр. Он просто передает метод, а затем пользователь внутренне должен совершать вызовы в экземпляры factory для объектов.

app.factory("Customerfactory", CreateCustomer);

Ниже приведено простое изображение, которое визуально показывает, как процесс DI для "Сервиса" отличается от "Factory" .

Изображение 3643

Factory следует использовать, когда мы хотим создать различные типы объектов в зависимости от сценариев. Например, в зависимости от сценария мы хотим создать простой объект "Клиент" или "Клиент" с объектом "Адрес" или "Клиент" с объектом "Телефон". Вот подробное объяснение этого пункта

Следует использовать службу. Когда у нас есть утилита или общие функции для ввода, такие как Utility, Logger, обработчик ошибок и т.д.

  • 0
    Каждый ответ, который я видел на этот и другие подобные вопросы, определяет разницу в механике и синтаксисе. Этот ответ дает реальную причину, по которой вы бы выбрали один над другим. Это вопрос семантики и рассмотрения названия, сервиса или фабрики, их назначения и способа их использования.
8

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

Служба в AngularJS является одноэлементным JavaScript-объектом, который содержит набор функций

var myModule = angular.module("myModule", []);

myModule.value  ("myValue"  , "12345");

function MyService(myValue) {
    this.doIt = function() {
        console.log("done: " + myValue;
    }
}

myModule.service("myService", MyService);
myModule.controller("MyController", function($scope, myService) {

    myService.doIt();

});

Factory стиль: (более сложный, но более сложный) возвращает возвращаемое значение функции: создайте экземпляр объекта как новый Object() в java.

Factory - это функция, которая создает значения. Когда службе, контроллеру и т.д. Требуется значение, введенное из factory, factory создает значение по требованию. После создания значение используется повторно для всех служб, контроллеров и т.д., Которые ему нужно вставить.

var myModule = angular.module("myModule", []);

myModule.value("numberValue", 999);

myModule.factory("myFactory", function(numberValue) {
    return "a value: " + numberValue;
})  
myModule.controller("MyController", function($scope, myFactory) {

    console.log(myFactory);

});

Провайдер style: (полная версия, конфигурируемая версия) возвращает результат функции $get function: Configurable.

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

var myModule = angular.module("myModule", []);

myModule.provider("mySecondService", function() {
    var provider = {};
    var config   = { configParam : "default" };

    provider.doConfig = function(configParam) {
        config.configParam = configParam;
    }

    provider.$get = function() {
        var service = {};

        service.doService = function() {
            console.log("mySecondService: " + config.configParam);
        }

        return service;
    }

    return provider;
});

myModule.config( function( mySecondServiceProvider ) {
    mySecondServiceProvider.doConfig("new config param");
});

myModule.controller("MyController", function($scope, mySecondService) {

    $scope.whenButtonClicked = function() {
        mySecondService.doIt();
    }

});

src jenkov

<!DOCTYPE html>
    <html ng-app="app">
    <head>
    	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
    	<meta charset=utf-8 />
    	<title>JS Bin</title>
    </head>
    <body ng-controller="MyCtrl">
    	{{serviceOutput}}
    	<br/><br/>
    	{{factoryOutput}}
    	<br/><br/>
    	{{providerOutput}}
    
    	<script>
    
    		var app = angular.module( 'app', [] );
    
    		var MyFunc = function() {
    
    			this.name = "default name";
    
    			this.$get = function() {
    				this.name = "new name"
    				return "Hello from MyFunc.$get(). this.name = " + this.name;
    			};
    
    			return "Hello from MyFunc(). this.name = " + this.name;
    		};
    
    		// returns the actual function
    		app.service( 'myService', MyFunc );
    
    		// returns the function return value
    		app.factory( 'myFactory', MyFunc );
    
    		// returns the output of the function $get function
    		app.provider( 'myProv', MyFunc );
    
    		function MyCtrl( $scope, myService, myFactory, myProv ) {
    
    			$scope.serviceOutput = "myService = " + myService;
    			$scope.factoryOutput = "myFactory = " + myFactory;
    			$scope.providerOutput = "myProvider = " + myProv;
    
    		}
    
    	</script>
    
    </body>
    </html>

jsbin

<!DOCTYPE html>
<html ng-app="myApp">
<head>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
	<meta charset=utf-8 />
	<title>JS Bin</title>
</head>
<body>
<div ng-controller="MyCtrl">
    {{hellos}}
</div>
	<script>

	var myApp = angular.module('myApp', []);

//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!"
    };
});

//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!"
        }
    };
});
    
//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!"
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});
        

function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
    
    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}
	</script>

</body>
</html>

jsfiddle

2

Мы можем определить такую ​​услугу:

app.service('MyService', function () {
   this.sayHello = function () {
      console.log('hello');
   };
});

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

Теперь то же самое, что и factory:

app.factory('MyService', function () {
    return {
       sayHello: function () {
           console.log('hello');
       }
    }
});

Опять же, .factory() - это метод на нашем модуле, а также имя и функция, определяющая factory. Мы можем вводить и использовать эту штуку точно так же, как и с сервисом. Какая разница здесь?

Ну, вы можете видеть, что вместо работы с этим в factory возвращались объектные литералы. Почему это? Оказывается, служба является функцией конструктора, тогда как factory - нет. Где-то глубоко внутри этого мира Angular, этот код вызывает функцию Object.create() с помощью функции конструктора службы, когда она создается. Однако функция factory - это просто функция, вызываемая, поэтому мы должны явно вернуть объект.

2

Служба AngularJS vs Factory

module.service( 'serviceName', function );

module.factory( 'factoryName', function );

При объявлении serviceName в качестве аргумента injectable вам будет предоставлен экземпляр функции. Другими словами, новый FunctionYouPassedToService(). Этот экземпляр объекта становится объектом службы, который AngularJS регистрирует и вводит позже другие services / controllers, если это необходимо.

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

В приведенном ниже примере мы определяем MyService двумя разными способами. Обратите внимание, как в .service мы создаем методы обслуживания с помощью this.methodname. В .factory мы создали объект factory и назначили ему методы.

AngularJS.service

module.service('MyService', function() {
    this.method1 = function() {
            //..
        }

    this.method2 = function() {
            //..
        }
});

AngularJS.factory

module.factory('MyService', function() {

    var factory = {}; 

    factory.method1 = function() {
            //..
        }

    factory.method2 = function() {
            //..
        }

    return factory;
});
2

Вот как я понял разницу между ними в плане дизайна:

Сервис. Верните тип, который будет создан для создания объекта такого типа. Если используется аналогия Java, служба возвращает определение класса Java.

Factory. Возвращает конкретный объект, который можно сразу использовать. В Java Analogy Factory возвращает объект Java.

Часть, которая часто путает людей (включая меня), заключается в том, что когда вы вводите в свой код услугу или Factory, их можно использовать одинаково, то, что вы получаете в своем коде в обоих случаях, является конкретным объектом, который вы можете сразу вызвать. Это означает, что в случае Сервиса angular вызывает от вас запрос "новый" в объявлении сервиса. Я думаю, что это сложная концепция.

2

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

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

Или в коротких словах "поставщик является более общей формой, а служба ограничена только объектами".

1

Для краткого и простого объяснения обратитесь https://stackoverflow.com/questions/13762228/confused-about-service-vs-factory.

Подробнее см. https://stackoverflow.com/questions/15666048/angularjs-service-vs-provider-vs-factory.

Также из документации angularJs: Изображение 3644

1

Существует три способа обработки бизнес-логики в AngularJS: (Вдохновленный курсом Yaakov Coursera AngularJS), которые:

  • Сервис
  • Factory
  • Provider

Здесь мы поговорим только о Сервис vs Factory

SERVICE

Синтаксис:

app.js

 var app = angular.module('ServiceExample',[]);
 var serviceExampleController =
              app.controller('ServiceExampleController', ServiceExampleController);
 var serviceExample = app.service('NameOfTheService', NameOfTheService);

 ServiceExampleController.$inject = ['NameOfTheService'] //very important as this protects from minification of js files

function ServiceExampleController(NameOfTheService){
     serviceExampleController = this;
     serviceExampleController.data = NameOfTheService.getSomeData();
 }

function NameOfTheService(){
     nameOfTheService = this;
     nameOfTheService.data = "Some Data";
     nameOfTheService.getSomeData = function(){
           return nameOfTheService.data;
     }     
}

index.html

<div ng-controller = "ServiceExampleController as serviceExample">
   {{serviceExample.data}}
</div>

Основные функции службы:

  • Lazily Instantiated: Если услуга не вводится, она не будет создана. Поэтому, чтобы использовать его, вам нужно будет вставить его в модуль.

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

Factory

Теперь поговорим о Factory в AngularJS

Сначала рассмотрим синтаксис:

app.js

var app = angular.module('FactoryExample',[]);
var factoryController = app.controller('FactoryController', FactoryController);
var factoryExampleOne = app.factory('NameOfTheFactoryOne', NameOfTheFactoryOne);
var factoryExampleTwo = app.factory('NameOfTheFactoryTwo', NameOfTheFactoryTwo);

//first implementation where it returns a function
function NameOfTheFactoryOne(){
   var factory = function(){
      return new SomeService();
    }
   return factory;
}

//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
   var factory = {
      getSomeService : function(){
          return new SomeService();
       }
    };
   return factory;
}

Теперь, используя приведенные выше два в контроллере:

 var factoryOne = NameOfTheFactoryOne() //since it returns a function
 factoryOne.someMethod();

 var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
 factoryTwo.someMethod();

Особенности Factory:

  • Эти виды услуг следуют шаблону factory. Factory можно рассматривать как центральное место, которое создает новые объекты или методы.

  • Это не только создает singleton, но и настраиваемые сервисы.

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

1
  • С factory вы фактически создаете объект внутри factory и возвращаете его.
  • При службе у вас есть стандартная функция , которая использует ключевое слово this для определения функция.
  • При использовании провайдера theres $get, который можно использовать , чтобы получить возвращаемый объект данные.
1

Это помогло мне понять разницу, благодаря сообщению в блоге Паскалем Пречтом.

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

Объекты, созданные с новым использованием, используют значение свойства prototype их функции-конструктора в качестве своего прототипа, поэтому я нашел код Angular, который вызывает Object.create(), который, я считаю, является функцией конструктора службы, когда он получает экземпляр, Однако функция factory - это просто функция, вызываемая, поэтому мы должны вернуть литерал объекта для factory.

Вот код Angular 1,5, который я нашел для factory:

var needsRecurse = false;
    var destination = copyType(source);

    if (destination === undefined) {
      destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
      needsRecurse = true;
    }

Angular фрагмент исходного кода для функции factory():

 function factory(name, factoryFn, enforce) {
    return provider(name, {
      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
    });
  }

Он принимает имя и функцию factory, которая передается, и возвращает поставщика с тем же именем, у которого есть метод $get, который является нашей функцией factory. Всякий раз, когда вы запрашиваете инжектор для конкретной зависимости, он в основном запрашивает соответствующего провайдера для экземпляра этой службы, вызывая метод $get(). Вот почему требуется $get() при создании поставщиков.

Вот код Angular 1.5 для службы.

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }

Оказывается, когда мы вызываем service(), он на самом деле вызывает factory()! Тем не менее, он не просто передаёт нашу функцию конструктора службы в factory как есть. Он также передает функцию, которая просит инжектор создать экземпляр объекта заданным конструктором.

Другими словами, если мы где-то добавляем MyService, то что происходит в коде:

MyServiceProvider.$get(); // return the instance of the service

Для повторного его повторения служба вызывает factory, который является методом $get() для соответствующего провайдера. Более того, $injector.instantiate() - это метод, который в конечном итоге вызывает Object.create() с помощью функции-конструктора. Вот почему мы используем "this" в сервисах.

Для ES5 не имеет значения, что мы используем: service() или factory(), всегда называемый factory, который создает поставщика для нашей службы.

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

Почему большинство людей рекомендуют использовать заводы над услугами? Это лучший ответ, который я видел из книги Павла Козловского: Освоение разработки веб-приложений с помощью AngularJS.

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

1

У меня была эта путаница на некоторое время, и я стараюсь изо всех сил дать здесь простое объяснение. Надеюсь, это поможет!

angular .factory и angular .service оба используются для инициализации службы и работы таким же образом.

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

Оба являются синглтонами


var app = angular.module('app', []);

<ч/" >

Factory

app.factory(<service name>, <function with a return value>)

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

например.

function myService() {
  //return what you want
  var service = {
    myfunc: function (param) { /* do stuff */ }
  }
  return service;
}

app.factory('myService', myService);

При вводе этой услуги (например, на ваш контроллер):

  • Angular будет вызывать вашу заданную функцию (как myService()), чтобы вернуть объект
  • Singleton - вызывается только один раз, сохраняется и передает один и тот же объект.

<ч/" >

Сервис

app.service(<service name>, <constructor function>)

Если вы хотите инициализировать свою службу из функции конструктора (используя ключевое слово this), вы должны использовать этот метод service.

например.

function myService() {
  this.myfunc: function (param) { /* do stuff */ }
}

app.service('myService', myService);

При вводе этой услуги (например, на ваш контроллер):

  • Angular будет new использовать вашу функцию (как new myService()), чтобы вернуть объект
  • Singleton - вызывается только один раз, сохраняется и передает один и тот же объект.

<ч/" > ПРИМЕЧАНИЕ. Если вы используете factory с <constructor function> или service с помощью <function with a return value>, это не сработает.


Примеры - DEMOs

1

Это будет лучший и короткий ответ для понимания Service Vs Factory Vs Provider

Источник: https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/HuZsOsMvKv4J

Здесь ben говорит демо http://jsbin.com/ohamub/1/edit?html,output

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

Услуги

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

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

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

Заводы

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

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

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

Провайдеры

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

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

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

0

Вы можете понять разницу с этой аналогией. Рассмотрим разницу между нормальной функцией, которая вернет некоторую функцию значения и конструктора, которая будет создаваться с использованием нового ключевого слова. Так что создание factory похоже на создание нормальной функции, которая вернется некоторая ценность (примитив или объект), тогда как создание службы похоже на создание функции-конструктора (класс OO), из которой мы можем создать экземпляр с использованием нового ключевого слова. Единственное, что нужно заметить, - это то, что, когда мы используем метод Service для создания сервисов, он автоматически создает экземпляр его с использованием механизма впрыска зависимостей, поддерживаемого AngularJS

Ещё вопросы

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