it-roy-ru.com

AngularJS: Сервис против провайдера против фабрики

Каковы различия между Service, Provider и Factory в AngularJS?

3267
Lior

Из списка рассылки AngularJS, который я получил удивительная тема , объясняет, что сервис против фабрики, против провайдера и их использование. Составление ответов:

Сервисы

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

Фабрики

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

Провайдеры

Синтаксис: module.provider( 'providerName', function );
Результат: при объявлении providerName в качестве вводимого аргумента вам будет предоставлен (new ProviderFunction()).$get(). Функция конструктора создается перед вызовом метода $ get - ProviderFunction - ссылка на функцию, переданную в module.provider.

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

Смотрите здесь для предоставленного кода.

Вот большое дальнейшее объяснение Миско:

provide.value('a', 123);

function Controller(a) {
  expect(a).toEqual(123);
}

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

provide.factory('b', function(a) {
  return a*2;
});

function Controller(b) {
  expect(b).toEqual(246);
}

Итак, factory - это функция, которая отвечает за создание значения. Обратите внимание, что фабричная функция может запрашивать другие зависимости.

Но что, если вы хотите быть более OO и ​​иметь класс с именем Greeter?

function Greeter(a) {
  this.greet = function() {
    return 'Hello ' + a;
  }
}

Тогда для создания экземпляра вам придется написать

provide.factory('greeter', function(a) {
  return new Greeter(a);
});

Тогда мы могли бы попросить "приветствовать" в контроллере, как это

function Controller(greeter) {
  expect(greeter instanceof Greeter).toBe(true);
  expect(greeter.greet()).toEqual('Hello 123');
}

Но это слишком многословно. Более короткий способ написать это будет provider.service('greeter', Greeter);

Но что, если мы хотим настроить класс Greeter до внедрения? Тогда мы могли бы написать

provide.provider('greeter2', function() {
  var salutation = 'Hello';
  this.setSalutation = function(s) {
    salutation = s;
  }

  function Greeter(a) {
    this.greet = function() {
      return salutation + ' ' + a;
    }
  }

  this.$get = function(a) {
    return new Greeter(a);
  };
});

Тогда мы можем сделать это:

angular.module('abc', []).config(function(greeter2Provider) {
  greeter2Provider.setSalutation('Halo');
});

function Controller(greeter2) {
  expect(greeter2.greet()).toEqual('Halo 123');
}

В качестве примечания, service, factory и value все получены от поставщика.

provider.service = function(name, Class) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.instantiate(Class);
    };
  });
}

provider.factory = function(name, factory) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.invoke(factory);
    };
  });
}

provider.value = function(name, value) {
  provider.factory(name, function() {
    return value;
  });
};
2850
Lior

JS Fiddle Demo

Пример "Hello world" с 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() {

    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 src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
    {{hellos}}
</div>
</body>
807
EpokK

TL; DR

1) Когда вы используете Factory, вы создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Когда вы передадите эту фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику.

app.controller(‘myFactoryCtrl’, function($scope, myFactory){
  $scope.artist = myFactory.getArtist();
});

app.factory(‘myFactory’, function(){
  var _artist = ‘Shakira’;
  var service = {};

  service.getArtist = function(){
    return _artist;
  }

  return service;
});


2) Когда вы используете Service, AngularJS создает его за кулисами с ключевым словом "new". По этой причине вы добавите свойства в "this", и сервис вернет "this". Когда вы передаете службу в свой контроллер, эти свойства в "this" теперь будут доступны на этом контроллере через вашу службу.

app.controller(‘myServiceCtrl’, function($scope, myService){
  $scope.artist = myService.getArtist();
});

app.service(‘myService’, function(){
  var _artist = ‘Nelly’;
  this.getArtist = function(){
    return _artist;
  }
});



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

app.controller(‘myProvider’, function($scope, myProvider){
  $scope.artist = myProvider.getArtist();
  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

app.provider(‘myProvider’, function(){
 //Only the next two lines are available in the app.config()
 this._artist = ‘’;
 this.thingFromConfig = ‘’;
  this.$get = function(){
    var that = this;
    return {
      getArtist: function(){
        return that._artist;
      },
      thingOnConfig: that.thingFromConfig
    }
  }
});

app.config(function(myProviderProvider){
  myProviderProvider.thingFromConfig = ‘This was set in config’;
});



не TL; DR

1) Фабрика
Фабрики - самый популярный способ создания и настройки сервиса. Там действительно не намного больше, чем то, что сказал TL; DR. Вы просто создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Затем, когда вы передадите фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику. Более подробный пример приведен ниже.

app.factory(‘myFactory’, function(){
  var service = {};
  return service;
});

Теперь любые свойства, которые мы прикрепляем к "сервису", будут доступны нам, когда мы передадим "myFactory" в наш контроллер.

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

app.factory(‘myFactory’, function($http, $q){
  var service = {};
  var baseUrl = ‘https://iTunes.Apple.com/search?term=’;
  var _artist = ‘’;
  var _finalUrl = ‘’;

  var makeUrl = function(){
   _artist = _artist.split(‘ ‘).join(‘+’);
    _finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
    return _finalUrl
  }

  return service;
});

Здесь вы заметите, что мы не привязываем эти переменные/функцию к "сервису". Мы просто создаем их, чтобы потом использовать или модифицировать их.

  • baseUrl - это базовый URL, который требуется iTunes API
  • _artist - художник, которого мы хотим найти
  • _finalUrl - это окончательный и полностью созданный URL-адрес, по которому мы сделаем звонок в iTunes.
  • makeUrl - это функция, которая создает и возвращает наш удобный для iTunes URL.

Теперь, когда наши вспомогательные/закрытые переменные и функции созданы, давайте добавим некоторые свойства к объекту "service". Все, что мы используем для "обслуживания", может быть непосредственно использовано внутри любого контроллера, в который мы передаем "myFactory".

Мы собираемся создать методы setArtist и getArtist, которые просто возвращают или устанавливают художника. Мы также собираемся создать метод, который будет вызывать iTunes API с нашим созданным URL. Этот метод возвращает обещание, которое будет выполнено, как только данные вернутся из iTunes API. Если у вас не было большого опыта использования обещаний в AngularJS, я настоятельно рекомендую глубоко погрузиться в них.

Ниже setArtist принимает исполнителя и позволяет установить исполнителя. getArtist возвращает художника. callItunes сначала вызывает makeUrl (), чтобы создать URL, который мы будем использовать с нашим запросом $ http. Затем он устанавливает объект обещания, делает запрос $ http с нашим окончательным URL, а затем, так как $ http возвращает обещание, мы можем вызвать .success или .error после нашего запроса. Затем мы выполняем свое обещание с помощью данных iTunes или отклоняем его с сообщением "Произошла ошибка".

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://iTunes.Apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  service.setArtist = function(artist){
    _artist = artist;
  }

  service.getArtist = function(){
    return _artist;
  }

  service.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

  return service;
});

Теперь наша фабрика завершена. Теперь мы можем внедрить "myFactory" в любой контроллер, а затем мы сможем вызывать наши методы, которые мы прикрепили к нашему сервисному объекту (setArtist, getArtist и callItunes).

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.data = {};
  $scope.updateArtist = function(){
    myFactory.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myFactory.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

В контроллере выше мы вводим в сервис "myFactory". Затем мы устанавливаем свойства для нашего объекта $ scope с данными из myFactory. Единственный сложный код выше, если вы никогда не имели дело с обещаниями раньше. Поскольку callItunes возвращает обещание, мы можем использовать метод .then () и устанавливать $ scope.data.artistData только после того, как наше обещание будет выполнено с данными iTunes. Вы заметите, что наш контроллер очень "тонкий" (это хорошая практика кодирования). Вся наша логика и постоянные данные находятся в нашем сервисе, а не в нашем контроллере.

2) Сервис
Пожалуй, самое важное, что нужно знать при создании Сервиса, это то, что он создается с помощью ключевого слова "new". Для вас, гуру JavaScript, это должно дать вам подсказку о природе кода. Для тех из вас, кто имеет ограниченный опыт работы с JavaScript, или для тех, кто не слишком знаком с тем, что на самом деле делает ключевое слово "new", давайте рассмотрим некоторые основы JavaScript, которые в конечном итоге помогут нам понять природу Сервиса.

Чтобы реально увидеть изменения, которые происходят при вызове функции с ключевым словом "new", давайте создадим функцию и вызовем ее с ключевым словом "new", а затем покажем, что делает интерпретатор, когда видит ключевое слово "new". Конечные результаты будут одинаковыми.

Сначала давайте создадим наш конструктор.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}

Это типичная функция конструктора JavaScript. Теперь всякий раз, когда мы вызываем функцию Person с помощью ключевого слова "new", "this" будет привязано к вновь созданному объекту.

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

Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}

Теперь, поскольку мы поместили функцию sayName в прототип, каждый экземпляр Person сможет вызывать функцию sayName, чтобы предупредить имя этого экземпляра.

Теперь, когда у нас есть функция конструктора Person и функция sayName в ее прототипе, давайте на самом деле создадим экземпляр Person, а затем вызовем функцию sayName.

var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

Таким образом, весь код для создания конструктора Person, добавления функции к его прототипу, создания экземпляра Person и последующего вызова функции для его прототипа выглядит следующим образом.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

Теперь давайте посмотрим, что на самом деле происходит, когда вы используете ключевое слово "new" в JavaScript. Первое, на что вы должны обратить внимание, - это то, что после использования "new" в нашем примере мы можем вызывать метод (sayName) для "tyler" так же, как если бы это был объект - так оно и есть. Итак, во-первых, мы знаем, что наш конструктор Person возвращает объект, видим ли мы это в коде или нет. Во-вторых, мы знаем, что, поскольку наша функция sayName расположена в прототипе, а не непосредственно в экземпляре Person, объект, который возвращает функция Person, должен делегировать своему прототипу при неудачных поисках. Проще говоря, когда мы вызываем tyler.sayName (), интерпретатор говорит: "Хорошо, я собираюсь посмотреть на только что созданный объект" tyler ", найти функцию sayName и затем вызвать ее. Подождите минуту, я не вижу здесь этого - все, что я вижу, это имя и возраст, позвольте мне проверить прототип. Да, похоже, что это на прототипе, позвольте мне это назвать ".

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

var Person = function(name, age){
  //The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
  //var obj = Object.create(Person.prototype);

  //The line directly below this sets ‘this’ to the newly created object
  //this = obj;

  this.name = name;
  this.age = age;

  //return this;
}

Теперь, имея представление о том, что на самом деле делает "новое" ключевое слово в JavaScript, создание службы в AngularJS должно быть проще для понимания.

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

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

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

app.service('myService', function($http, $q){
  var baseUrl = 'https://iTunes.Apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
});

Теперь мы прикрепим все наши методы, которые будут доступны в нашем контроллере, к "этому".

app.service('myService', function($http, $q){
  var baseUrl = 'https://iTunes.Apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.setArtist = function(artist){
    _artist = artist;
  }

  this.getArtist = function(){
    return _artist;
  }

  this.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

});

Теперь, как и на нашей фабрике, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myService. Вот контроллер myService (который почти такой же, как наш заводской контроллер).

app.controller('myServiceCtrl', function($scope, myService){
  $scope.data = {};
  $scope.updateArtist = function(){
    myService.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myService.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

Как я уже упоминал ранее, когда вы действительно поймете, что "новое" делает, Сервисы практически идентичны фабрикам в AngularJS.

) Провайдер

Самое важное, что следует помнить о провайдерах, это то, что они являются единственной службой, которую вы можете передать в часть app.config вашего приложения. Это имеет огромное значение, если вам нужно изменить некоторую часть объекта службы, прежде чем он станет доступен где-либо еще в вашем приложении. Хотя они очень похожи на Услуги/Фабрики, есть несколько различий, которые мы обсудим.

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

app.provider('myProvider', function(){
   var baseUrl = 'https://iTunes.Apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below.
  this.thingFromConfig = ‘’;

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
}

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

Вы можете думать о провайдерах как о трех разделах. Первый раздел - это "закрытые" переменные/функции, которые будут изменены/установлены позже (показано выше). Второй раздел - это переменные/функции, которые будут доступны в вашей функции app.config и, следовательно, доступны для изменения до того, как они станут доступны где-либо еще (также показано выше). Важно отметить, что эти переменные должны быть присоединены к ключевому слову "this". В нашем примере только "thingFromConfig" будет доступен для изменения в app.config. Третий раздел (показанный ниже) - это все переменные/функции, которые будут доступны в вашем контроллере, когда вы передадите службу myProvider в этот конкретный контроллер.

При создании службы с провайдером единственными свойствами/методами, которые будут доступны в вашем контроллере, являются те свойства/методы, которые возвращаются из функции $ get (). Приведенный ниже код помещает $ get в "this" (которое, как мы знаем, будет возвращено из этой функции) Теперь эта функция $ get возвращает все методы/свойства, которые мы хотим быть доступными в контроллере. Вот пример кода.

this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }

Теперь полный код провайдера выглядит следующим образом

app.provider('myProvider', function(){
  var baseUrl = 'https://iTunes.Apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below
  this.thingFromConfig = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }
});

Теперь, как и на нашей фабрике, Service, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myProvider. Вот контроллер myProvider (который почти такой же, как наш заводской/сервисный контроллер).

app.controller('myProviderCtrl', function($scope, myProvider){
  $scope.data = {};
  $scope.updateArtist = function(){
    myProvider.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myProvider.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }

  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

Как упоминалось ранее, весь смысл создания службы с помощью Provider заключается в возможности изменять некоторые переменные с помощью функции app.config до того, как конечный объект будет передан остальной части приложения. Давайте посмотрим на пример этого.

app.config(function(myProviderProvider){
  //Providers are the only service you can pass into app.config
  myProviderProvider.thingFromConfig = 'This sentence was set in app.config. Providers are the only service that can be passed into config. Check out the code to see how it works';
});

Теперь вы можете видеть, что "thingFromConfig" - это пустая строка в нашем провайдере, но когда она появится в DOM, это будет "Это предложение было установлено…".

638
Tyler McGinnis

Понимание AngularJS Factory, Service и Provider

Все они используются для совместного использования одноразовых объектов. Это помогает обмениваться повторно используемым кодом через ваше приложение/различные компоненты/модули.

Из Документов ( Сервис/Завод :

  • Ленивый экземпляр - Angular создает экземпляр службы/фабрики только тогда, когда от нее зависит компонент приложения.
  • Singletons - каждый компонент, зависящий от службы, получает ссылку на один экземпляр, сгенерированный фабрикой сервисов.

Завод

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

app.factory('MyFactory', function() {
    var serviceObj = {};
    //creating an object with methods/functions or variables
    serviceObj.myFunction = function() {
        //TO DO:
    };
    //return that object
    return serviceObj;
});

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

Это может быть просто набор функций, таких как класс. Следовательно, он может быть создан в разных контроллерах, когда вы вводите его в функции контроллера/фабрики/директивы. Он создается только один раз за приложение.

Обслуживание

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

app.service('MyService', function() {
    //directly binding events to this context
    this.myServiceFunction = function() {
        //TO DO:
    };
});

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

Используйте его, когда вам нужно совместно использовать один объект во всем приложении. Например, данные пользователя, прошедшего проверку подлинности, методы/данные для совместного использования, функции служебных программ и т.д.

Поставщик

Поставщик используется для создания настраиваемого объекта службы. Вы можете настроить параметры сервиса из функции конфигурации. Возвращает значение с помощью функции $get(). Функция $get выполняется в фазе выполнения в угловом режиме.

app.provider('configurableService', function() {
    var name = '';
    //this method can be be available at configuration time inside app.config.
    this.setName = function(newName) {
        name = newName;
    };
    this.$get = function() {
        var getName = function() {
             return name;
        };
        return {
            getName: getName //exposed object to where it gets injected.
        };
    };
});

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

Когда вам нужно предоставить модульную конфигурацию для вашего сервисного объекта, прежде чем сделать его доступным, например. Предположим, вы хотите установить URL-адрес API на основе вашей среды, например dev, stage или prod

ПРИМЕЧАНИЕ

Только поставщик будет доступен в фазе конфигурации angular, а сервис и фабрика - нет.

Надеюсь, это прояснило ваше понимание Фабрики, Сервиса и Поставщика .

222
Pankaj Parkar

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

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

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

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

  1. a сохраненное значение происходит от запуска fn.
  2. Сохраненное значение b происходит из newing fn.
  3. Хранимое значение c приходит сначала от получения экземпляра с помощью newing fn, а затем от запуска метода $get экземпляра.

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

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

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

191
Lucia

Сервис против провайдера против фабрики:

Я пытаюсь сделать это простым. Это все о базовой концепции JavaScript.

Прежде всего, давайте поговорим об сервисах в AngularJS!

Что такое Сервис: В AngularJS, Сервис - это не что иное, как одиночный JavaScript объект, который может хранить некоторые полезные методы или свойства. Этот одноэлементный объект создается на основе ngApp (приложения Angular) и используется всеми контроллерами в текущем приложении. Когда Angularjs создает объект службы, он регистрирует этот объект службы с уникальным именем службы. Поэтому каждый раз, когда нам нужен экземпляр службы, Angular ищет в реестре это имя службы, и она возвращает ссылку на объект службы. Так что мы можем вызывать метод, обращаться к свойствам и т.д. На объекте службы. У вас может возникнуть вопрос, можете ли вы также поместить свойства, методы в объектную область контроллеров! Так зачем вам сервисный объект? Ответы таковы: сервисы распределяются между несколькими контроллерами. Если вы поместите некоторые свойства/методы в объект области видимости контроллера, он будет доступен только для текущей области видимости. Но когда вы определяете методы, свойства для объекта службы, он будет доступен глобально и может быть доступен в любой области контроллера путем внедрения этой службы.

Таким образом, если имеется три области контроллера, пусть это будут controllerA, controllerB и controllerC, все они будут использовать один и тот же экземпляр службы.

<div ng-controller='controllerA'>
    <!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
    <!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
    <!-- controllerC scope -->
</div>

Как создать сервис?

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

используйте эту ссылку для ссылки на код

Заводская функция:

Мы можем определить фабричную функцию, как показано ниже.

factory('serviceName',function fnFactory(){ return serviceInstance;})

AngularJS предоставляет 'factory (' serviceName ', fnFactory)' метод, который принимает два параметра, serviceName и функцию JavaScript. Angular создает экземпляр службы, вызывая функцию fnFactory () , как показано ниже.

var serviceInstace = fnFactory();

Переданная функция может определить объект и вернуть этот объект. AngularJS просто сохраняет эту ссылку на объект в переменную, которая передается в качестве первого аргумента. Все, что возвращается из fnFactory, будет связано с serviceInstance. Вместо того, чтобы возвращать объект, мы также можем возвращать функцию, значения и т.д. Что бы мы ни возвращали, они будут доступны экземпляру службы.

Пример:

var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
  var data={
    'firstName':'Tom',
    'lastName':' Cruise',
    greet: function(){
      console.log('hello!' + this.firstName + this.lastName);
    }
  };

  //Now all the properties and methods of data object will be available in our service object
  return data;
});

Сервисная функция:

service('serviceName',function fnServiceConstructor(){})

Это еще один способ, мы можем зарегистрировать услугу. Единственное отличие состоит в том, как AngularJS пытается создать экземпляр объекта службы. На этот раз angular использует ключевое слово 'new' и вызывает функцию конструктора примерно так, как показано ниже.

var serviceInstance = new fnServiceConstructor();

В функции конструктора мы можем использовать ключевое слово this для добавления свойств/методов к объекту службы. пример:

//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
  this.firstName ='James';
  this.lastName =' Bond';
  this.greet = function(){
    console.log('My Name is '+ this.firstName + this.lastName);
  };
});

Функция провайдера:

Функция Provider () - это еще один способ создания сервисов. Пусть нам интересно создать сервис, который просто отображает какое-то приветственное сообщение пользователю. Но мы также хотим предоставить такую ​​функциональность, чтобы пользователь мог установить собственное приветственное сообщение. В техническом плане мы хотим создавать настраиваемые сервисы. Как мы можем это сделать ? Должен быть способ, чтобы приложение могло передавать свои пользовательские приветственные сообщения, а Angularjs делал бы его доступным для функции фабрики/конструктора, которая создает наш экземпляр сервисов. В таком случае функция provider () выполняет свою работу. используя функцию provider (), мы можем создавать настраиваемые сервисы.

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

/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});

/*step2:configure the service */
app.config(function configureService(serviceProvider){});

Как внутренне работает синтаксис провайдера?

1.Provider объект создается с помощью функции конструктора, которую мы определили в нашей функции провайдера.

var serviceProvider = new serviceProviderConstructor();

2. Функция, которую мы передали в app.config (), выполняется. Это называется этапом конфигурации, и здесь у нас есть возможность настроить наш сервис.

configureService(serviceProvider);

3. Наконец, экземпляр службы создается путем вызова $ get метода serviceProvider.

serviceInstance = serviceProvider.$get()

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

var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
  //this function works as constructor function for provider
  this.firstName = 'Arnold ';
  this.lastName = ' Schwarzenegger' ;
  this.greetMessage = ' Welcome, This is default Greeting Message' ;
  //adding some method which we can call in app.config() function
  this.setGreetMsg = function(msg){
    if(msg){
      this.greetMessage =  msg ;
    }
  };

  //We can also add a method which can change firstName and lastName
  this.$get = function(){
    var firstName = this.firstName;
    var lastName = this.lastName ;
    var greetMessage = this.greetMessage;
    var data={
       greet: function(){
         console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
       }
    };
    return data ;
  };
});

app.config(
  function(providerPatternProvider){
    providerPatternProvider.setGreetMsg(' How do you do ?');
  }
);

Рабочая демоверсия

Резюме:


Фабрика использует фабричную функцию, которая возвращает экземпляр службы. serviceInstance = fnFactory ();

Служба использует функцию конструктора и Angular вызывает эту функцию конструктора, используя ключевое слово 'new' для создания экземпляра службы. serviceInstance = new fnServiceConstructor ();

Provider определяет функцию providerConstructor, эта функция providerConstructor определяет фабричную функцию $ get Angular вызывает $ get () для создания объекта службы. Синтаксис провайдера имеет дополнительное преимущество в настройке объекта службы перед его созданием. serviceInstance = $ get ();

135
Anant

Как правильно отметили несколько человек, фабрика, поставщик, сервис и даже значение и константа являются версиями одного и того же. Вы можете разбить более общее provider на все из них. Вот так:

enter image description here

Вот статья, из которой это изображение:

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

84
Luis Perez

Завод

Вы даете AngularJS функцию, AngularJS будет кешировать и вводить возвращаемое значение, когда запрашивается фабрика.

Пример:

app.factory('factory', function() {
    var name = '';
    // Return value **is** the object that will be injected
    return {
        name: name;
    }
})

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

app.controller('ctrl', function($scope, factory) {
     $scope.name = factory.name;
});

Обслуживание

Вы даете AngularJS функцию, AngularJS вызовет new , чтобы создать ее экземпляр. Это экземпляр, который создает AngularJS, который будет кэшироваться и вставляться при запросе сервиса. Поскольку new был использован для создания экземпляра службы, ключевое слово this является действительным и относится к экземпляру.

Пример:

app.service('service', function() {
     var name = '';
     this.setName = function(newName) {
         name = newName;
     }
     this.getName = function() {
         return name;
     }
});

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

app.controller('ctrl', function($scope, service) {
   $scope.name = service.getName();
});

Поставщик

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

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

Пример:

app.provider('provider', function() {
     var name = '';
     this.setName = function(newName) {
          name = newName;
     }
     this.$get = function() {
         return {
            name: name
         }
     }
})

Использование (как инъекция в контроллере)

app.controller('ctrl', function($scope, provider) {
    $scope.name = provider.name;
});

Использование (настройка поставщика перед вызовом $get для создания инъекционного)

app.config(function(providerProvider) {
    providerProvider.setName('John');
});
62
pixelbits

Я заметил кое-что интересное, играя с провайдерами.

Видимость инъекционных препаратов различна для поставщиков, чем для служб и предприятий. Если вы объявите AngularJS "константой" (например, myApp.constant('a', 'Robert');), вы можете внедрить ее в службы, фабрики и поставщиков.

Но если вы объявите AngularJS "значение" (например, myApp.value('b', {name: 'Jones'});), вы можете внедрить его в службы и фабрики, но НЕ в функцию создания провайдера. Однако вы можете добавить его в функцию $get, которую вы определили для своего провайдера. Это упоминается в документации AngularJS, но это легко пропустить. Вы можете найти его на странице% provide в разделах о методах value и constant.

http://jsfiddle.net/R2Frv/1/

<div ng-app="MyAppName">
    <div ng-controller="MyCtrl">
        <p>from Service: {{servGreet}}</p>
        <p>from Provider: {{provGreet}}</p>
    </div>
</div>
<script>
    var myApp = angular.module('MyAppName', []);

    myApp.constant('a', 'Robert');
    myApp.value('b', {name: 'Jones'});

    myApp.service('greetService', function(a,b) {
        this.greeter = 'Hi there, ' + a + ' ' + b.name;
    });

    myApp.provider('greetProvider', function(a) {
        this.firstName = a;
        this.$get = function(b) {
            this.lastName = b.name;
            this.fullName = this.firstName + ' ' + this.lastName;
            return this;
        };
    });

    function MyCtrl($scope, greetService, greetProvider) {
        $scope.servGreet = greetService.greeter;
        $scope.provGreet = greetProvider.fullName;
    }
</script>
55
justlooking

Это очень запутанная часть для новичка, и я попытался объяснить это простыми словами

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

В сервисе мы создаем имена функций как свойство с этим объектом.

AngularJS Factory: назначение Factory также совпадает с Service, однако в этом случае мы создаем новый объект и добавляем функции в качестве свойств этого объекта и в В конце мы возвращаем этот объект.

AngularJS Provider: цель этого снова та же, однако Provider выдает выходные данные своей функции $ get.

Определение и использование Сервиса, Фабрики и Поставщика объясняется по адресу http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider

44
Sheo Narayan

Для меня лучший и самый простой способ понять разницу это:

var service, factory;
service = factory = function(injection) {}

Как AngularJS создает конкретные компоненты (упрощенно):

// service
var angularService = new service(injection);

// factory
var angularFactory = factory(injection);

Таким образом, для службы то, что становится компонентом AngularJS, является экземпляром объекта класса, который представлен функцией объявления службы. Для фабрики это результат, возвращаемый функцией объявления фабрики. Фабрика может вести себя так же, как сервис:

var factoryAsService = function(injection) {
  return new function(injection) {
    // Service content
  }
}

Самый простой способ мышления следующий:

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

Пример фабричного "класса" представлен в комментариях, а также о разнице поставщиков.

34
Lukasz Frankowski

Мои разъяснения по этому вопросу:

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

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

Существует много уровней сложности при создании значений для "глобальных переменных":

  1. Constant
    Это определяет фактическую константу, которая не должна изменяться в течение всего приложения, как и константы в других языках (чего нет в JavaScript).
  2. Значение
    Это изменяемое значение или объект, и он служит некоторой глобальной переменной, которая может даже вводиться при создании других служб или фабрик (см. Далее). Однако это должно быть буквальное значение "", что означает, что нужно выписать фактическое значение и не может использовать какую-либо логику вычислений или программирования (другими словами 39 или myText или {prop: "value"} в порядке, но 2 +2 нет).
  3. Factory
    Более общее значение, которое можно вычислить сразу. Он работает путем передачи функции в AngularJS с логикой, необходимой для вычисления значения, и AngularJS выполняет ее, и сохраняет возвращаемое значение в именованной переменной.
    Обратите внимание, что можно вернуть объект (в этом случае он будет функционировать аналогично службе ) или функции (которая будет сохранена в переменной как функция обратного вызова).
  4. Сервис
    Сервис - это более упрощенная версия фабрики , которая действительна только в том случае, если значение является объектом, и она позволяет писать любую логику непосредственно в функции. (как если бы это был конструктор), а также объявление и доступ к свойствам объекта с помощью ключевого слова this .
  5. Provider
    В отличие от сервиса, который является упрощенной версией фабрики , провайдер является более сложным, но более гибким способом инициализации "глобальных" переменных с наибольшим гибкость, позволяющая устанавливать значения из app.config.
    Это работает как использование комбинации сервиса и провайдера , передавая провайдеру функцию с объявленными свойствами используя ключевое слово this , которое можно использовать из app.config.
    Затем он должен иметь отдельную функцию $. Get , которая выполняется AngularJS после установки вышеуказанных свойств через файл app.config, и это Функция $. get ведет себя так же, как и фабрика , указанная выше, в том смысле, что ее возвращаемое значение используется для инициализации "глобальных" переменных.
33
yoel halb

Мое понимание очень просто ниже.

Factory: Вы просто создаете объект внутри фабрики и возвращаете его.

Service:

У вас просто есть стандартная функция, которая использует это ключевое слово для определения функции.

Поставщик:

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

26
sajan

Резюме от Angular Docs :

  • Существует пять типов рецептов, которые определяют, как создавать объекты: Value, - Заводской, Сервис, Поставщик и Постоянная.
  • Factory и Service - наиболее часто используемые рецепты. Единственная разница между ними заключается в том, что рецепт службы лучше работает для объектов пользовательского типа, тогда как фабрика может создавать примитивы и функции JavaScript.
  • Рецепт является основным типом рецепта, а все остальные являются просто синтаксическим сахаром.
  • Поставщик - самый сложный тип рецепта. Вам это не нужно, если вы не создаете многократно используемый код, который нуждается в глобальной настройке.

enter image description here


Лучшие ответы от SO:

https://stackoverflow.com/a/26924234/16567 (<- ХОРОШО) https://stackoverflow.com/a/27263882/16567
https://stackoverflow.com/a/16566144/16567

24
Yarin

Все хорошие ответы уже. Я хотел бы добавить еще несколько пунктов о Service и Factory. Вместе с разницей между сервисом/фабрикой. И можно также иметь такие вопросы, как:

  1. Должен ли я использовать сервис или фабрику? В чем разница?
  2. Они делают то же самое или ведут себя одинаково?

Давайте начнем с разницы между обслуживанием и фабрикой:

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

  2. Может использоваться для моделирования объекта с поведением: Они могут иметь методы, внутренние переменные состояния и т.д. Хотя способ написания этого кода будет отличаться.

Услуги:

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

  1. Функции и переменные экземпляра будут свойствами this.
  2. Вам не нужно возвращать значение. Когда Angular вызывает new yourServiceName(), он получает объект this со всеми свойствами, которые вы наделили на него.

Пример примера:

angular.service('MyService', function() {
  this.aServiceVariable = "Ved Prakash"
  this.aServiceMethod = function() {
    return //code
  };
});

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

будьте осторожны с this:

Поскольку созданный сервис является объектом, методы внутри него могут ссылаться на него при вызове:

angular.service('ScoreKeeper', function($http) {
  this.score = 0;

  this.getScore = function() {
    return this.score;
  };

  this.setScore = function(newScore) {
    this.score = newScore;
  };

  this.addOne = function() {
    this.score++;
  };
});

Возможно, у вас возникнет соблазн вызвать ScoreKeeper.setScore в цепочке обещаний, например, если вы инициализировали счет, взяв его с сервера: $http.get('/score').then(ScoreKeeper.setScore). Проблема в том, что ScoreKeeper.setScore будет вызываться с this, привязанным к null, и вы получите ошибки. Лучший способ был бы $http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper)). Если вы решите использовать это в своих методах обслуживания или нет, будьте осторожны, как вы их называете.

Возвращение значения из Service:

Из-за того, как работают конструкторы JavaScript, если вы возвращаете сложное значение (i.e., an Object) из функции constructor, вызывающая сторона получит этот объект вместо этого экземпляра.

Это означает, что вы можете в основном скопировать и вставить пример фабрики снизу, заменить factory на service, и это будет работать:

angular.service('MyService', function($http) {
  var api = {};

  api.aServiceMethod= function() {
    return $http.get('/users');
  };
  return api;
});

Поэтому, когда Angular создает ваш сервис с новым MyService (), он получит этот объект API вместо экземпляра MyService.

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

заводы:

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

angular.factory('MyFactory', function($http) {
  var api = {};

  api.aFactoryMethod= function() {
    return $http.get('/users');
  };

  return api;
});

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

Ответы на вопросы 1 и 2 выше:

По большей части, просто используйте фабрики для всего. Их поведение легче понять. Не нужно выбирать, возвращать ли значение или нет, и, кроме того, нет ошибок, если вы поступите неправильно.

Я все еще называю их "услугами", когда говорю о введении их как зависимостей.

Поведение Service/Factory очень похоже, и некоторые люди скажут, что любой из них в порядке. Это несколько верно, но мне легче следовать советам руководства по стилю Джона Папы и просто придерживаться заводов. **

16
Ved

Уже есть хорошие ответы, но я просто хочу поделиться этим.

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

И Значение, Фабрика, Сервис и Константа (4 способа) - синтаксический поставщик сахара путь/рецепт.

Существует часть Service vs Factory: https://www.youtube.com/watch?v=BLzNCkPn3ao

Сервис полностью связан с ключевым словом new, которое, как мы знаем, выполняет 4 вещи:

  1. создает новый объект
  2. связывает его с его объектом prototype
  3. соединяет context с this
  4. и возвращает this

И Factory это все о Factory Pattern - содержит функции, которые возвращают объекты, подобные этой службе.

  1. возможность использования других сервисов (есть зависимости)
  2. инициализация сервиса
  3. отложенная/ленивая инициализация

И это простое/короткое видео: также охватывает провайдера : https://www.youtube.com/watch?v=HvTZbQ_hUZY = (там видно, как они переходят с завода на провайдера)

Рецепт провайдера используется в основном в конфигурации приложения до того, как приложение полностью запустится/инициализируется.

16
ses

Дополнительным разъяснением является то, что фабрики могут создавать функции/примитивы, а службы - нет. Проверьте это jsFiddle на основе Epokk's: http://jsfiddle.net/skeller88/PxdSP/1351/ .

Фабрика возвращает функцию, которую можно вызвать:

myApp.factory('helloWorldFromFactory', function() {
  return function() {
    return "Hello, World!";
  };
});

Фабрика также может вернуть объект с методом, который может быть вызван:

myApp.factory('helloWorldFromFactory', function() {
  return {
    sayHello: function() {
      return "Hello, World!";
    }
  };
});

Служба возвращает объект с методом, который может быть вызван:

myApp.service('helloWorldFromService', function() {
  this.sayHello = function() {
     return "Hello, World!";
  };
});

Для получения дополнительной информации см. Сообщение, которое я написал о разнице: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/

16
skeller88

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

  • Инжектор использует рецепты для создания двух типов объектов: сервисов и объектов специального назначения.
  • Существует пять типов рецептов, которые определяют, как создавать объекты: Value, Factory, Service, Provider и Constant.
  • Фабрика и Сервис - наиболее часто используемые рецепты. Единственная разница между ними заключается в том, что рецепт Service лучше работает для объектов пользовательского типа, тогда как Factory может создавать примитивы и функции JavaScript.
  • Рецепт провайдера - это основной тип рецепта, а все остальные - просто синтаксический сахар.
  • Поставщик - самый сложный тип рецепта. Вам это не нужно, если вы не создаете многократно используемый код, который нуждается в глобальной настройке.
  • Все объекты специального назначения, кроме Контроллера, определяются с помощью заводских рецептов.

enter image description here

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

  1. Если вы хотите использовать в angular, функция настройки модуля должна быть создана как провайдер
angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})
  1. Ajax-вызов или сторонняя интеграция должны быть сервисом .
  2. Для манипуляций с данными создайте их как фабрику

Для базовых сценариев фабрика и сервис ведут себя одинаково.

14
BEJGAM SHIVA PRASAD

Вот пример кода, который я придумал как шаблон кода для фабрики объектов в AngularjS. Я использовал Car/CarFactory в качестве примера для иллюстрации. Делает для простой реализации кода в контроллере.

     <script>
        angular.module('app', [])
            .factory('CarFactory', function() {

                /**
                 * BroilerPlate Object Instance Factory Definition / Example
                 */
                this.Car = function() {

                    // initialize instance properties
                    angular.extend(this, {
                        color           : null,
                        numberOfDoors   : null,
                        hasFancyRadio   : null,
                        hasLeatherSeats : null
                    });

                    // generic setter (with optional default value)
                    this.set = function(key, value, defaultValue, allowUndefined) {

                        // by default,
                        if (typeof allowUndefined === 'undefined') {
                            // we don't allow setter to accept "undefined" as a value
                            allowUndefined = false;
                        }
                        // if we do not allow undefined values, and..
                        if (!allowUndefined) {
                            // if an undefined value was passed in
                            if (value === undefined) {
                                // and a default value was specified
                                if (defaultValue !== undefined) {
                                    // use the specified default value
                                    value = defaultValue;
                                } else {
                                    // otherwise use the class.prototype.defaults value
                                    value = this.defaults[key];
                                } // end if/else
                            } // end if
                        } // end if

                        // update 
                        this[key] = value;

                        // return reference to this object (fluent)
                        return this;

                    }; // end this.set()

                }; // end this.Car class definition

                // instance properties default values
                this.Car.prototype.defaults = {
                    color: 'yellow',
                    numberOfDoors: 2,
                    hasLeatherSeats: null,
                    hasFancyRadio: false
                };

                // instance factory method / constructor
                this.Car.prototype.instance = function(params) {
                    return new 
                        this.constructor()
                                .set('color',           params.color)
                                .set('numberOfDoors',   params.numberOfDoors)
                                .set('hasFancyRadio',   params.hasFancyRadio)
                                .set('hasLeatherSeats', params.hasLeatherSeats)
                    ;
                };

                return new this.Car();

            }) // end Factory Definition
            .controller('testCtrl', function($scope, CarFactory) {

                window.testCtrl = $scope;

                // first car, is red, uses class default for:
                // numberOfDoors, and hasLeatherSeats
                $scope.car1     = CarFactory
                                    .instance({
                                        color: 'red'
                                    })
                                ;

                // second car, is blue, has 3 doors, 
                // uses class default for hasLeatherSeats
                $scope.car2     = CarFactory
                                    .instance({
                                        color: 'blue',
                                        numberOfDoors: 3
                                    })
                                ;
                // third car, has 4 doors, uses class default for 
                // color and hasLeatherSeats
                $scope.car3     = CarFactory
                                    .instance({
                                        numberOfDoors: 4
                                    })
                                ;
                // sets an undefined variable for 'hasFancyRadio',
                // explicitly defines "true" as default when value is undefined
                $scope.hasFancyRadio = undefined;
                $scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);

                // fourth car, purple, 4 doors,
                // uses class default for hasLeatherSeats
                $scope.car4     = CarFactory
                                    .instance({
                                        color: 'purple',
                                        numberOfDoors: 4
                                    });
                // and then explicitly sets hasLeatherSeats to undefined
                $scope.hasLeatherSeats = undefined;
                $scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);

                // in console, type window.testCtrl to see the resulting objects

            });
    </script>

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

    angular.module('app')
.factory('PositionFactory', function() {

    /**
     * BroilerPlate Object Instance Factory Definition / Example
     */
    this.Position = function() {

        // initialize instance properties 
        // (multiple properties to satisfy multiple external interface contracts)
        angular.extend(this, {
            lat         : null,
            lon         : null,
            latitude    : null,
            longitude   : null,
            coords: {
                latitude: null,
                longitude: null
            }
        });

        this.setLatitude = function(latitude) {
            this.latitude           = latitude;
            this.lat                = latitude;
            this.coords.latitude    = latitude;
            return this;
        };
        this.setLongitude = function(longitude) {
            this.longitude          = longitude;
            this.lon                = longitude;
            this.coords.longitude   = longitude;
            return this;
        };

    }; // end class definition

    // instance factory method / constructor
    this.Position.prototype.instance = function(params) {
        return new 
            this.constructor()
                    .setLatitude(params.latitude)
                    .setLongitude(params.longitude)
        ;
    };

    return new this.Position();

}) // end Factory Definition

.controller('testCtrl', function($scope, PositionFactory) {
    $scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
    $scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller

;

13
James Earlywine

Используя в качестве ссылки эту страницу и документацию (которая, по-видимому, значительно улучшилась со времени моего последнего просмотра), я собрал следующую демонстрацию реального (-ish) мира, в которой используются 4 из 5 вариантов поставщик; Значение, Постоянный, Заводской и полноценный Провайдер.

HTML:

<div ng-controller="mainCtrl as main">
    <h1>{{main.title}}*</h1>
    <h2>{{main.strapline}}</h2>
    <p>Earn {{main.earn}} per click</p>
    <p>You've earned {{main.earned}} by clicking!</p>
    <button ng-click="main.handleClick()">Click me to earn</button>
    <small>* Not actual money</small>
</div>

приложение

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

// A CONSTANT is not going to change
app.constant('range', 100);

// A VALUE could change, but probably / typically doesn't
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');

// A simple FACTORY allows us to compute a value @ runtime.
// Furthermore, it can have other dependencies injected into it such
// as our range constant.
app.factory('random', function randomFactory(range) {
    // Get a random number within the range defined in our CONSTANT
    return Math.random() * range;
});

// A PROVIDER, must return a custom type which implements the functionality 
// provided by our service (see what I did there?).
// Here we define the constructor for the custom type the PROVIDER below will 
// instantiate and return.
var Money = function(locale) {

    // Depending on locale string set during config phase, we'll
    // use different symbols and positioning for any values we 
    // need to display as currency
    this.settings = {
        uk: {
            front: true,
            currency: '£',
            thousand: ',',
            decimal: '.'
        },
        eu: {
            front: false,
            currency: '€',
            thousand: '.',
            decimal: ','
        }
    };

    this.locale = locale;
};

// Return a monetary value with currency symbol and placement, and decimal 
// and thousand delimiters according to the locale set in the config phase.
Money.prototype.convertValue = function(value) {

    var settings = this.settings[this.locale],
        decimalIndex, converted;

    converted = this.addThousandSeparator(value.toFixed(2), settings.thousand);

    decimalIndex = converted.length - 3;

    converted = converted.substr(0, decimalIndex) +
        settings.decimal +
        converted.substr(decimalIndex + 1);    

    converted = settings.front ?
            settings.currency + converted : 
            converted + settings.currency; 

    return converted;   
};

// Add supplied thousand separator to supplied value
Money.prototype.addThousandSeparator = function(value, symbol) {
   return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);
};

// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY
// are all effectively syntactic sugar built on top of the PROVIDER construct
// One of the advantages of the PROVIDER is that we can configure it before the
// application starts (see config below).
app.provider('money', function MoneyProvider() {

    var locale;

    // Function called by the config to set up the provider
    this.setLocale = function(value) {
        locale = value;   
    };

    // All providers need to implement a $get method which returns
    // an instance of the custom class which constitutes the service
    this.$get = function moneyFactory() {
        return new Money(locale);
    };
});

// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider', function(moneyProvider) {
    moneyProvider.setLocale('uk');
    //moneyProvider.setLocale('eu'); 
}]);

// The ubiquitous controller
app.controller('mainCtrl', function($scope, title, strapline, random, money) {

    // Plain old VALUE(s)
    this.title = title;
    this.strapline = strapline;

    this.count = 0;

    // Compute values using our money provider    
    this.earn = money.convertValue(random); // random is computed @ runtime
    this.earned = money.convertValue(0);

    this.handleClick = function() { 
        this.count ++;
        this.earned = money.convertValue(random * this.count);
    };
});

Рабочая демо .

12
net.uk.sweet

Этот ответ обратиться к теме/вопросу

как Factory, Service и Constant - просто синтаксический сахар поверх рецепта поставщика?

ИЛИ

как фабрика, сервис и провайдеры внутренне симилар

в основном то, что происходит

Когда вы создаете factory(), он устанавливает function, предоставленный во втором аргументе, для $get провайдера и возвращает его (provider(name, {$get:factoryFn })), все, что вы получаете, это provider, но нет другого свойства/метода, кроме $get этого provider (означает, что вы не можете настроить это)

Исходный код фабрики

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

При создании service() он возвращает вас, предоставляя factory () с function, который внедряет constructor (возвращает экземпляр конструктора, предоставленного вами в вашем сервисе) и возвращает его

Исходный код сервиса

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

Таким образом, в основном в обоих случаях вы в конечном итоге получаете $ провайдера, настроенного на вашу функцию, которую вы предоставили, но вы можете дать что-то большее, чем $ get, как вы могли изначально предоставить в provider () для блока конфигурации

12
A.B

Я знаю много отличных ответов, но я должен поделиться своим опытом использования
1. service для большинства случаев по умолчанию
2. factory используется для создания службы этого конкретного экземпляра

// factory.js ////////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];

function xFactoryImp($http) {
    var fac = function (params) {
        this._params = params; // used for query params
    };

    fac.prototype.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }
    return fac;
}
})();

// service.js //////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];

function xServiceImp($http) {  
    this._params = {'model': 'account','mode': 'list'};

    this.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }       
}
})();

и используя:

controller: ['xFactory', 'xService', function(xFactory, xService){

        // books = new instance of xFactory for query 'book' model
        var books = new xFactory({'model': 'book', 'mode': 'list'});

        // accounts = new instance of xFactory for query 'accounts' model
        var accounts = new xFactory({'model': 'account', 'mode': 'list'});

        // accounts2 = accounts variable
        var accounts2 = xService;
... 
11
nguyên

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

Angular предоставляет нам три способа создания и регистрации нашего собственного сервиса.

1) Фабрика

2) Сервис

3) Провайдер

Factory: Фабрика - это простая функция, которая позволяет добавить некоторую логику перед созданием объекта. Возвращает созданный объект.

Это просто набор функций, таких как класс. Следовательно, он может быть создан в разных контроллерах, когда вы используете его с функцией конструктора.

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

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

Provider: Поставщик используется для создания настраиваемого объекта службы. Возвращает значение с помощью функции $ get ().

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

Запустите следующий код и посмотрите вывод.

<!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's return value
        app.factory( 'myFactory', MyFunc );
        // returns the output of the function's $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>
10
Saniya syed qureshi

Немного опоздал на вечеринку. Но я подумал, что это более полезно для тех, кто хотел бы узнать (или иметь ясность) о разработке Angular JS Custom Services с использованием методологий фабрики, сервиса и провайдера.

Я наткнулся на это видео, в котором четко объясняются методологии фабрики, сервиса и провайдера для разработки пользовательских сервисов AngularJS:

https://www.youtube.com/watch?v=oUXku28ex-M

Исходный код: http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service

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

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

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
  function($scope, calcFactory) {
    $scope.a = 10;
    $scope.b = 20;

    $scope.doSum = function() {
      //$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
      calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
        $scope.sum = r;
      });
    };

  }
]);

app.factory('calcFactory', ['$http', '$log',
  function($http, $log) {
    $log.log("instantiating calcFactory..");
    var oCalcService = {};

    //oCalcService.getSum = function(a,b){
    //  return parseInt(a) + parseInt(b);
    //};

    //oCalcService.getSum = function(a, b, cb){
    //  var s = parseInt(a) + parseInt(b);
    //  cb(s);
    //};

    oCalcService.getSum = function(a, b, cb) { //using http service

      $http({
        url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
        method: 'GET'
      }).then(function(resp) {
        $log.log(resp.data);
        cb(resp.data);
      }, function(resp) {
        $log.error("ERROR occurred");
      });
    };

    return oCalcService;
  }
]);

Код для "сервисной" методологии для пользовательских сервисов (это очень похоже на "фабрику", но отличается от синтаксической точки зрения):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
        $scope.a = 10;
        $scope.b = 20;

        $scope.doSum = function(){
                //$scope.sum = calcService.getSum($scope.a, $scope.b);
                
                calcService.getSum($scope.a, $scope.b, function(r){
                        $scope.sum = r;
                });             
        };

}]);

app.service('calcService', ['$http', '$log', function($http, $log){
        $log.log("instantiating calcService..");
        
        //this.getSum = function(a,b){
        //      return parseInt(a) + parseInt(b);
        //};

        //this.getSum = function(a, b, cb){
        //      var s = parseInt(a) + parseInt(b);
        //      cb(s);
        //};

        this.getSum = function(a, b, cb){
                $http({
                        url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
                        method: 'GET'
                }).then(function(resp){
                        $log.log(resp.data);
                        cb(resp.data);
                },function(resp){
                        $log.error("ERROR occurred");
                });
        };

}]);

Код для методологии "провайдера" для пользовательских сервисов (это необходимо, если вы хотите разработать сервис, который можно настроить):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
        $scope.a = 10;
        $scope.b = 20;

        $scope.doSum = function(){
                //$scope.sum = calcService.getSum($scope.a, $scope.b);
                
                calcService.getSum($scope.a, $scope.b, function(r){
                        $scope.sum = r;
                });             
        };

}]);

app.provider('calcService', function(){

        var baseUrl = '';

        this.config = function(url){
                baseUrl = url;
        };

        this.$get = ['$log', '$http', function($log, $http){
                $log.log("instantiating calcService...")
                var oCalcService = {};

                //oCalcService.getSum = function(a,b){
                //      return parseInt(a) + parseInt(b);
                //};

                //oCalcService.getSum = function(a, b, cb){
                //      var s = parseInt(a) + parseInt(b);
                //      cb(s);  
                //};

                oCalcService.getSum = function(a, b, cb){

                        $http({
                                url: baseUrl + '/Sum?a=' + a + '&b=' + b,
                                method: 'GET'
                        }).then(function(resp){
                                $log.log(resp.data);
                                cb(resp.data);
                        },function(resp){
                                $log.error("ERROR occurred");
                        });
                };              

                return oCalcService;
        }];

});

app.config(['calcServiceProvider', function(calcServiceProvider){
        calcServiceProvider.config("http://localhost:4467");
}]);

Наконец, пользовательский интерфейс, который работает с любым из вышеперечисленных сервисов:

<html>
<head>
        <title></title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
        <script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
        <div ng-controller="emp">
                <div>
                        Value of a is {{a}},
                        but you can change
                        <input type=text ng-model="a" /> <br>

                        Value of b is {{b}},
                        but you can change
                        <input type=text ng-model="b" /> <br>

                </div>
                Sum = {{sum}}<br>
                <button ng-click="doSum()">Calculate</button>
        </div>
</body>
</html>
10
user203687

Просто чтобы прояснить ситуацию, из источника AngularJS вы можете увидеть, что сервис просто вызывает фабричную функцию, которая, в свою очередь, вызывает функцию провайдера:

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

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

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

СЕРВИС:

Синтаксис:

app.js

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

 ServiceExampleController.$inject = ['NameOfTheService'] //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>

Особенности сервиса:

  1. Ленивый экземпляр : если он не введен, он никогда не будет создан. Таким образом, чтобы использовать его, придется ввести его в модуль.
  2. Singleton : при внедрении в несколько модулей все будут иметь доступ только к одному конкретному экземпляру. Именно поэтому очень удобно обмениваться данными между разными контроллерами.

ФАБРИКА

Сначала давайте посмотрим на синтаксис:

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();

Особенности Фабрики:

  1. Следует шаблону фабричного дизайна. Фабрика - это центральное место, которое производит новые объекты или функции.
  2. Производит не только синглтон, но и настраиваемые сервисы.
  3. Метод .service() - это фабрика, который всегда предоставляет один и тот же тип сервиса, который является одноэлементным, и без какого-либо простого способа настроить его поведение. Этот метод .service() обычно используется как ярлык для чего-то, что не требует какой-либо настройки.

ПОСТАВЩИК

Давайте снова посмотрим на синтаксис первым:

angular.module('ProviderModule', [])
.controller('ProviderModuleController', ProviderModuleController)
.provider('ServiceProvider', ServiceProvider)
.config(Config); //optional

Config.$inject = ['ServiceProvider'];
function Config(ServiceProvider) {
  ServiceProvider.defaults.maxItems = 10; //some default value
}


ProviderModuleController.$inject = ['ServiceProvider'];
function ProviderModuleController(ServiceProvider) {
  //some methods
}

function ServiceProvider() {
  var provider = this;

  provider.defaults = {
    maxItems: 10
  };

  provider.$get = function () {
    var someList = new someListService(provider.defaults.maxItems);

    return someList;
  };
}

}

Особенности провайдера:

  1. Провайдер - самый гибкий метод создания сервисов в Angular.
  2. Мы не только можем создать фабрику, которая динамически конфигурируется, но во время использования фабрики с помощью метода провайдера мы могли настраивать фабрику только один раз при начальной загрузке всего нашего приложения.
  3. Завод может быть использован во всем приложении с пользовательскими настройками. Другими словами, мы можем настроить эту фабрику до запуска приложения. Фактически в документации angular упоминается, что метод провайдера - это то, что фактически выполняется за кулисами, когда мы конфигурируем наши сервисы с помощью методов .service или .factory.
  4. $get - это функция, которая напрямую связана с экземпляром провайдера. Эта функция заводская функция. Другими словами, он похож на тот, который мы используем для предоставления методу .factory. В этой функции мы создаем наш собственный сервис. Это свойство $get, это функция, которая делает провайдера провайдером. AngularJS ожидает, что у провайдера есть свойство $ get, значением которого является функция, которую Angular будет рассматривать как фабричную функцию. Но что делает эту настройку всего провайдера очень особенной, тот факт, что мы можем предоставить некоторый объект config внутри провайдера услуг, и это обычно идет со значениями по умолчанию, которые мы можем позже перезаписать на шаге, где мы можем сконфигурировать все приложение.
9
Pritam Banerjee

Factory: Фабрика, вы фактически создаете объект внутри фабрики и возвращаете его.
service: Служба, у вас просто есть стандартная функция, которая использует ключевое слово this для определения функции.
provider: У провайдера есть $ get, который вы определили, и его можно использовать для получения объекта, который возвращает данные.

7
MR Kesavan

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

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

Вот краткое изложение того, когда использовать каждый:

Factory: Предоставляемое вами значение должно быть рассчитано на основе других данных.

Служба: Вы возвращаете объект с методами.

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

7
eGhoul

1.Услуги - это одноэлементные объекты, которые создаются при необходимости и никогда не очищаются до конца жизненного цикла приложения (когда браузер закрыт). Контроллеры уничтожаются и очищаются, когда они больше не нужны.

2. Самый простой способ создать сервис - использовать метод factory (). Метод factory () позволяет нам определять службу, возвращая объект, который содержит функции службы и данные службы. Функция определения сервиса - это место, где мы размещаем наши инъекционные сервисы, такие как $ http и $ q. Пример:

angular.module('myApp.services')
.factory('User', function($http) { // injectables go here
var backendUrl = "http://localhost:3000"; var service = {
    // our factory definition
user: {},
setName: function(newName) {
      service.user['name'] = newName;
    },
setEmail: function(newEmail) { service.user['email'] = newEmail;
},
save: function() {
return $http.post(backendUrl + '/users', { user: service.user
}); }
};
return service; });

Используя factory () в нашем приложении

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

angular.module('myApp')
.controller('MainController', function($scope, User) {
  $scope.saveUser = User.save;
});
  1. Метод service (), с другой стороны, позволяет нам создавать сервис, определяя функцию конструктора. Мы можем использовать прототипный объект для определения нашего сервиса вместо необработанного объекта JavaScript. Подобно методу factory (), мы также установим инъецируемые элементы в определении функции.
  2. Самым низким способом создания сервиса является использование метода provide (). Это единственный способ создать службу, которую мы можем настроить с помощью функции .config (). В отличие от предыдущих методов, мы устанавливаем инъецируемые значения в определении функции this. $ Get ().
4
Shankar Gangadhar