Question AngularJS: Service vs fournisseur vs usine


Quelles sont les différences entre un Service, Provider et Factory dans AngularJS?


3163
2018-03-27 17:59


origine


Réponses:


De la liste de diffusion AngularJS j'ai eu un fil incroyable cela explique service vs usine vs fournisseur et leur utilisation d'injection. Compiler les réponses:

Prestations de service

Syntaxe: module.service( 'serviceName', function ); 
Résultat: lors de la déclaration de serviceName en tant qu'argument injectable Vous recevrez une instance de la fonction. En d'autres termes  new FunctionYouPassedToService().

Des usines

Syntaxe: module.factory( 'factoryName', function ); 
Résultat: Lorsque vous déclarez factoryName comme argument injectable, vous recevrez la valeur renvoyée en appelant la référence de la fonction passée à module.factory.

Fournisseurs

Syntaxe: module.provider( 'providerName', function ); 
Résultat: lors de la déclaration de providerName en tant qu'argument injectable vous serez fourni avec  (new ProviderFunction()).$get(). La fonction constructeur est instanciée avant que la méthode $ get ne soit appelée - ProviderFunction est la référence de la fonction passée à module.provider.

Les fournisseurs ont l'avantage de pouvoir être configurés pendant la phase de configuration du module.

Voir ici pour le code fourni.

Voici une autre explication de Misko:

provide.value('a', 123);

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

Dans ce cas, l'injecteur renvoie simplement la valeur telle quelle. Mais que faire si vous voulez calculer la valeur? Ensuite, utilisez une usine

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

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

Alors factory est une fonction qui est responsable de la création de la valeur. Notez que la fonction d'usine peut demander d'autres dépendances.

Mais que faire si vous voulez être plus OO et avoir une classe appelée Greeter?

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

Ensuite, pour instancier vous auriez à écrire

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

Ensuite, nous pourrions demander "greeter" dans le contrôleur comme celui-ci

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

Mais c'est trop verbeux. Un moyen plus court d'écrire ceci serait provider.service('greeter', Greeter);

Mais que faire si nous voulions configurer le Greeter classe avant l'injection? Ensuite, nous pourrions écrire

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

Alors nous pouvons faire ceci:

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

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

En remarque, service, factory, et value sont tous dérivés du fournisseur.

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

2800
2017-07-30 10:20



JS Fiddle Demo

Exemple "Bonjour tout le monde" avec 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>


796
2018-05-15 15:53



TL; DR 

1) Lorsque vous utilisez un Usine vous créez un objet, lui ajoutez des propriétés, puis renvoyez le même objet. Lorsque vous passez cette usine dans votre contrôleur, ces propriétés sur l'objet seront désormais disponibles dans ce contrôleur via votre usine.

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) Lorsque vous utilisez Un service, AngularJS l'instancie dans les coulisses avec le mot-clé 'new'. À cause de cela, vous ajouterez des propriétés à 'ceci' et le service retournera 'ceci'. Lorsque vous passez le service dans votre contrôleur, ces propriétés sur 'this' seront désormais disponibles sur ce contrôleur via votre service.

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

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



3)  Fournisseurs sont le seul service que vous pouvez transmettre dans votre fonction .config (). Utilisez un fournisseur lorsque vous souhaitez fournir une configuration à l'échelle du module pour votre objet de service avant de le rendre disponible.

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’;
});



Non TL; DR

1) Usine 
Les usines sont le moyen le plus populaire de créer et de configurer un service. Il n'y a vraiment pas beaucoup plus que ce que le TL, DR a dit. Vous venez de créer un objet, y ajouter des propriétés, puis retourner ce même objet. Ensuite, lorsque vous passez l'usine dans votre contrôleur, ces propriétés sur l'objet seront désormais disponibles dans ce contrôleur via votre usine. Un exemple plus complet est ci-dessous.

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

Maintenant, toutes les propriétés que nous attachons à 'service' seront disponibles lorsque nous passerons 'myFactory' dans notre contrôleur.

Ajoutons maintenant des variables 'privées' à notre fonction de rappel. Ceux-ci ne seront pas directement accessibles depuis le contrôleur, mais nous mettrons éventuellement en place des méthodes de getter / setter sur 'service' pour pouvoir modifier ces variables 'privées' en cas de besoin.

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

Ici, vous remarquerez que nous n'attachons pas ces variables / fonctions à «service». Nous les créons simplement pour les utiliser ou les modifier plus tard.

  • baseUrl est l'URL de base requise par l'API iTunes
  • _artist est l'artiste que nous souhaitons consulter
  • _finalUrl est l'URL finale et complète à laquelle nous allons appeler iTunes.
  • makeUrl est une fonction qui créera et retournera notre URL conviviale iTunes.

Maintenant que nos variables et fonctions auxiliaires / privées sont en place, ajoutons quelques propriétés à l'objet 'service'. Tout ce que nous mettons sur 'service' peut être directement utilisé dans n'importe quel contrôleur dans lequel nous transmettons 'myFactory'.

Nous allons créer des méthodes setArtist et getArtist qui retournent ou définissent simplement l'artiste. Nous allons également créer une méthode qui appellera l'API iTunes avec notre URL créée. Cette méthode va renvoyer une promesse qui se réalisera une fois que les données seront revenues de l'API iTunes. Si vous n'avez pas beaucoup d'expérience dans l'utilisation des promesses dans AngularJS, je vous recommande fortement de faire un plongeon profond sur eux.

Au dessous de setArtist accepte un artiste et vous permet de définir l'artiste. getArtist renvoie l'artiste. callItunes appelle d'abord makeUrl () afin de construire l'URL que nous utiliserons avec notre requête $ http. Ensuite, il crée un objet de promesse, fait une requête $ http avec notre URL finale, puis parce que $ http renvoie une promesse, nous sommes capables d'appeler .success ou .error après notre requête. Nous résolvons ensuite notre promesse avec les données iTunes, ou nous le rejetons avec un message disant "Il y avait une erreur".

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

Maintenant, notre usine est terminée. Nous sommes maintenant capables d'injecter myFactory dans n'importe quel contrôleur et nous pourrons ensuite appeler nos méthodes que nous avons attachées à notre objet service (setArtist, getArtist et 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);
      })
  }
});

Dans le contrôleur ci-dessus, nous injectons dans le service 'myFactory'. Nous définissons ensuite les propriétés de notre objet $ scope avec les données de 'myFactory'. Le seul code difficile ci-dessus est si vous n'avez jamais eu de promesses auparavant. Parce que callItunes renvoie une promesse, nous sommes en mesure d'utiliser la méthode .then () et seulement définir $ scope.data.artistData une fois que notre promesse est remplie avec les données iTunes. Vous remarquerez que notre contrôleur est très «mince» (c'est une bonne pratique de codage). Toutes nos données logiques et persistantes sont situées dans notre service, pas dans notre contrôleur.

2) Service 
Peut-être que la plus grande chose à savoir lors de la création d'un Service est qu'il est instancié avec le mot-clé «nouveau». Pour vous, les gourous JavaScript, cela devrait vous donner une grande indication sur la nature du code. Pour ceux d'entre vous qui ont une connaissance limitée de JavaScript ou pour ceux qui ne connaissent pas très bien le nouveau mot clé, passons en revue certains fondamentaux de JavaScript qui nous aideront éventuellement à comprendre la nature d'un Service.

Pour vraiment voir les changements qui se produisent lorsque vous invoquez une fonction avec le mot-clé 'new', créons une fonction et invoquons-la avec le mot-clé 'new', puis montrons ce que fait l'interpréteur quand il voit le mot-clé 'new'. Les résultats finaux seront les mêmes.

D'abord, créons notre constructeur.

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

C'est une fonction de constructeur JavaScript typique. Maintenant, chaque fois que nous invoquons la fonction Person en utilisant le mot clé 'new', 'this' sera lié à l'objet nouvellement créé.

Maintenant, ajoutons une méthode sur le prototype de notre Personne afin qu'elle soit disponible sur chaque instance de notre 'classe' Personne.

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

Maintenant, parce que nous mettons la fonction sayName sur le prototype, chaque instance de Person pourra appeler la fonction sayName afin d'alerter le nom de cette instance.

Maintenant que nous avons notre fonction de constructeur Person et notre fonction sayName sur son prototype, créons en fait une instance de Person puis appelons la fonction sayName.

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

Donc, tous ensemble, le code pour créer un constructeur Person, ajouter une fonction à son prototype, créer une instance Person, puis appeler la fonction sur son prototype ressemble à ceci.

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’

Voyons maintenant ce qui se passe réellement lorsque vous utilisez le mot-clé 'new' en JavaScript. La première chose que vous devriez remarquer est qu'après avoir utilisé 'new' dans notre exemple, nous sommes capables d'appeler une méthode (sayName) sur 'tyler' comme s'il s'agissait d'un objet - c'est parce que c'est le cas. Donc d'abord, nous savons que notre constructeur Person renvoie un objet, que nous puissions le voir dans le code ou non. Deuxièmement, nous savons que parce que notre fonction sayName est située sur le prototype et pas directement sur l'instance de Person, l'objet renvoyé par la fonction Person doit être délégué à son prototype lors des recherches échouées. En termes plus simples, lorsque nous appelons tyler.sayName (), l'interpréteur dit "OK, je vais regarder l'objet 'tyler' que nous venons de créer, localiser la fonction sayName, puis l'appeler. Attendez une minute, je ne la vois pas ici - tout ce que je vois c'est le nom et l'âge, laissez-moi vérifier le prototype. Ouais, on dirait que c'est sur le prototype, laissez-moi l'appeler. ".

Vous trouverez ci-dessous un code pour savoir ce que le mot-clé 'new' fait réellement en JavaScript. C'est fondamentalement un exemple de code du paragraphe ci-dessus. J'ai mis la 'vue de l'interprète' ou la façon dont l'interprète voit le code à l'intérieur des notes.

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;
}

Ayant maintenant cette connaissance de ce que le mot-clé 'new' fait vraiment dans JavaScript, la création d'un Service dans AngularJS devrait être plus facile à comprendre.

La plus grande chose à comprendre lors de la création d'un Service est de savoir que les Services sont instanciés avec le mot-clé «nouveau». En combinant cette connaissance avec nos exemples ci-dessus, vous devriez maintenant reconnaître que vous allez attacher vos propriétés et méthodes directement à 'ceci' qui sera ensuite renvoyé par le Service lui-même. Jetons un coup d'oeil à ceci dans l'action.

Contrairement à ce que nous avions fait avec l'exemple Factory, nous n'avons pas besoin de créer un objet puis de retourner cet objet car, comme mentionné plusieurs fois auparavant, nous avons utilisé le mot clé 'new' pour que l'interpréteur crée cet objet. c'est un prototype, puis retournez-le pour nous sans que nous ayons à faire le travail.

Tout d'abord, créons notre fonction «privée» et assistante. Cela devrait sembler très familier puisque nous avons fait exactement la même chose avec notre usine. Je ne vais pas expliquer ce que chaque ligne fait ici parce que je l'ai fait dans l'exemple de l'usine, si vous êtes confus, relisez l'exemple de l'usine.

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

Maintenant, nous allons attacher toutes nos méthodes qui seront disponibles dans notre contrôleur à 'ceci'.

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;
  }

});

Maintenant, tout comme dans notre usine, setArtist, getArtist et callItunes seront disponibles dans n'importe quel contrôleur auquel nous transmettons myService. Voici le contrôleur myService (qui est presque exactement le même que notre contrôleur d'usine).

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

Comme je l'ai mentionné précédemment, une fois que vous comprenez vraiment ce que «nouveau» fait, les services sont presque identiques aux usines dans AngularJS.

3) Fournisseur

La plus grande chose à retenir à propos des fournisseurs est qu'ils sont le seul service que vous pouvez passer dans la partie app.config de votre application. Ceci est d'une importance capitale si vous avez besoin de modifier une partie de votre objet de service avant qu'il ne soit disponible partout ailleurs dans votre application. Bien que très semblable aux services / usines, il y a quelques différences dont nous discuterons.

Nous avons d'abord mis en place notre fournisseur de la même manière que nous l'avons fait avec notre service et notre usine. Les variables ci-dessous sont notre fonction «privée» et auxiliaire.

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;
  }
}

* Encore une fois, si une partie du code ci-dessus est confuse, consultez la section Usine où j'explique ce que tout cela fait plus de détails.

Vous pouvez considérer les fournisseurs comme ayant trois sections. La première section est les variables / fonctions 'privées' qui seront modifiées / définies plus tard (voir ci-dessus). La deuxième section est les variables / fonctions qui seront disponibles dans votre fonction app.config et qui sont donc disponibles pour être modifiées avant qu'elles ne soient disponibles ailleurs (également montré ci-dessus). Il est important de noter que ces variables doivent être attachées au mot clé "this". Dans notre exemple, seul 'thingFromConfig' sera disponible pour modifier dans le fichier app.config. La troisième section (illustrée ci-dessous) est l'ensemble des variables / fonctions qui seront disponibles dans votre contrôleur lorsque vous passerez le service 'myProvider' dans ce contrôleur spécifique.

Lors de la création d'un service avec Provider, les seules propriétés / méthodes qui seront disponibles dans votre contrôleur sont les propriétés / méthodes renvoyées par la fonction $ get (). Le code ci-dessous met $ get on 'this' (qui, nous le savons, sera finalement retourné depuis cette fonction). Maintenant, cette fonction $ get retourne toutes les méthodes / propriétés que nous voulons être disponibles dans le contrôleur. Voici un exemple de code.

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
    }
  }

Maintenant, le code du fournisseur complet ressemble à ceci

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

Maintenant, tout comme dans notre usine et Service, setArtist, getArtist, et callItunes seront disponibles dans n'importe quel contrôleur dans lequel nous passons myProvider. Voici le contrôleur myProvider (qui est presque exactement le même que notre contrôleur d'usine / service).

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

Comme mentionné précédemment, le but de la création d'un service avec Provider est de pouvoir modifier certaines variables via la fonction app.config avant que l'objet final ne soit transmis au reste de l'application. Voyons voir un exemple de cela.

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';
});

Maintenant, vous pouvez voir comment 'thingFromConfig' est une chaîne vide dans notre fournisseur, mais quand cela apparaît dans le DOM, ce sera 'Cette phrase a été définie ...'.


618
2017-12-24 13:15



Tous les services sont singletons; ils sont instanciés une fois par application. Ils peuvent être de tout type, qu'il s'agisse d'une primitive, d'un littéral d'objet, d'une fonction ou même d'une instance d'un type personnalisé.

le value, factory, service, constant, et provider les méthodes sont tous les fournisseurs. Ils enseignent à l'Injecteur comment instancier les Services.

Le plus détaillé, mais aussi le plus complet est un fournisseur   recette. le quatre restants types de recettes - Valeur, Usine, Service et   Constant - ne sont que du sucre syntaxique au-dessus d'une recette de fournisseur.

  • le Recette de valeur est le cas le plus simple, où vous instancier le service vous-même et fournir le valeur instanciée à l'injecteur.
  • le Recette d'usine donne à l'Injecteur une fonction d'usine qu'il appelle lorsqu'il a besoin d'instancier le service. Lorsqu'il est appelé, le fonction d'usine crée et retourne l'instance de service. Les dépendances du Service sont injectées en tant qu'arguments des fonctions. Donc, en utilisant cette recette ajoute les capacités suivantes:
    • Possibilité d'utiliser d'autres services (avoir des dépendances)
    • Initialisation du service
    • Initialisation retardée / paresseuse
  • le Recette de service est presque la même que la recette d'usine, mais ici l'Injector invoque un constructeur avec le nouvel opérateur au lieu d'une fonction d'usine.
  • le Recette du fournisseur est habituellement surpuissance. Il ajoute une couche supplémentaire d'indirection en vous permettant de configurer la création de l'usine.

Vous devez utiliser la recette du fournisseur uniquement lorsque vous souhaitez exposer une API   pour la configuration à l'échelle de l'application qui doit être faite avant la   l'application commence. Ceci est généralement intéressant uniquement pour réutilisable   services dont le comportement pourrait devoir varier légèrement entre   applications.


506
2018-02-01 12:58



Comprendre l'usine, le service et le fournisseur AngularJS

Tous ces éléments sont utilisés pour partager des objets singleton réutilisables. Il permet de partager du code réutilisable à travers votre application / divers composants / modules.

De Docs Service / Usine:

  • Instancié paresseusement - Angular n'instancie un service / factory que lorsqu'un composant d'application en dépend.
  • Singletons - Chaque composant   dépendant d'un service obtient une référence à l'instance unique   généré par l'usine de service.

Usine

Une fabrique est une fonction où vous pouvez manipuler / ajouter de la logique avant de créer un objet, puis l'objet nouvellement créé est renvoyé.

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

Usage

Ce peut être juste une collection de fonctions comme une classe. Par conséquent, il peut être instancié dans différents contrôleurs lorsque vous l'injectez dans vos fonctions contrôleur / usine / directive. Il est instancié une seule fois par application.

Un service

Simplement en regardant les services réfléchir sur le prototype de tableau. Un service est une fonction qui instancie un nouvel objet en utilisant le mot-clé 'new'. Vous pouvez ajouter des propriétés et des fonctions à un objet de service en utilisant thismot-clé. Contrairement à une usine, elle ne renvoie rien (elle retourne un objet qui contient des méthodes / propriétés).

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

Usage

Utilisez-le lorsque vous avez besoin de partager un seul objet dans toute l'application. Par exemple, les détails des utilisateurs authentifiés, les méthodes / données partageables, les fonctions utilitaires, etc.

Fournisseur

Un fournisseur est utilisé pour créer un objet de service configurable. Vous pouvez configurer le paramètre de service à partir de la fonction de configuration. Il renvoie une valeur en utilisant le $get() fonction. le $get La fonction est exécutée sur la phase d'exécution en angulaire.

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.
        };
    };
});

Usage

Lorsque vous devez fournir une configuration par module pour votre objet de service avant de le rendre disponible, par exemple. supposons que vous voulez définir votre URL API sur la base de votre environnement comme dev, stage ou prod

REMARQUE 

Seul le fournisseur sera disponible en phase de configuration d'angulaire, tandis que   le service et l'usine ne sont pas.

J'espère que cela a éclairci votre compréhension de Usine, service et fournisseur.


221
2017-11-14 06:25



Pour moi, la révélation est venue quand j'ai réalisé qu'ils travaillent tous de la même manière: en faisant quelque chose une fois que, stockant la valeur qu'ils obtiennent, puis cracher cette même valeur stockée lorsqu'il est référencé par injection de dépendance.

Disons que nous avons:

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

La différence entre les trois est la suivante:

  1. ala valeur stockée vient de courir fn.
  2. bLa valeur stockée vient de newing fn.
  3. cLa valeur stockée vient d'abord obtenir une instance par newing fn, puis en cours d'exécution d'un $get méthode de l'instance.

Ce qui signifie qu'il y a quelque chose comme un objet cache dans AngularJS, dont la valeur de chaque injection n'est attribuée qu'une seule fois, quand ils ont été injectés la première fois, et où:

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

C'est pourquoi nous utilisons this dans les services, et définir un this.$get dans les fournisseurs.


190
2017-07-22 11:39



Service vs fournisseur vs usine:

J'essaie de garder les choses simples. Tout est sur le concept JavaScript de base.

Tout d'abord, parlons de prestations de service dans AngularJS!

Quel est le service: Dans AngularJS, Un service n'est rien d'autre qu'un objet JavaScript singleton qui peut stocker certaines méthodes ou propriétés utiles. Cet objet singleton est créé par base ngApp (application angulaire) et il est partagé entre tous les contrôleurs de l'application en cours. Lorsque Angularjs instancie un objet de service, il enregistre cet objet de service avec un nom de service unique. Ainsi, chaque fois que nous avons besoin d'une instance de service, Angular recherche dans le registre ce nom de service et renvoie la référence à l'objet de service. Tels que nous pouvons invoquer la méthode, accéder aux propriétés etc sur l'objet de service. Vous pouvez vous demander si vous pouvez également mettre des propriétés, des méthodes sur l'objet de portée des contrôleurs! Alors pourquoi avez-vous besoin d'un objet de service? Réponses: les services sont partagés entre plusieurs contrôleurs. Si vous mettez des propriétés / méthodes dans l'objet de portée d'un contrôleur, elles ne seront disponibles que pour la portée actuelle. Mais lorsque vous définissez des méthodes, des propriétés sur un objet de service, elles seront disponibles globalement et peuvent être accédées dans la portée de tout contrôleur en injectant ce service.

Donc, s'il y a trois contrôleurs, que ce soit controllerA, controllerB et controllerC, tous partagent la même instance de service.

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

Comment créer un service?

AngularJS fournit différentes méthodes pour enregistrer un service. Ici nous allons nous concentrer sur trois méthodes usine (..), service (..), fournisseur (..);

Utilisez ce lien pour la référence de code

Fonction d'usine:

Nous pouvons définir une fonction d'usine comme ci-dessous.

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

AngularJS fournit 'factory (' serviceName ', fnFactory)' méthode qui prend deux paramètre, serviceName et une fonction JavaScript. Angular crée une instance de service en invoquant la fonction fnFactory () tel que ci-dessous.

var serviceInstace = fnFactory();

La fonction passée peut définir un objet et renvoyer cet objet. AngularJS stocke simplement cette référence d'objet à une variable qui est passée en premier argument. Tout ce qui est renvoyé par fnFactory sera lié à serviceInstance. Au lieu de retourner l'objet, nous pouvons aussi retourner la fonction, les valeurs, etc., Quoi que nous retournions, sera disponible pour l'instance de service.

Exemple:

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

Fonction de service:

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

C'est l'autre façon, nous pouvons enregistrer un service. La seule différence est la façon dont AngularJS essaie d'instancier l'objet service. Cette fois, angulaire utilise le mot-clé 'new' et appelle la fonction constructeur quelque chose comme ci-dessous.

var serviceInstance = new fnServiceConstructor();

Dans la fonction constructeur, nous pouvons utiliser le mot clé 'this' pour ajouter des propriétés / méthodes à l'objet service. Exemple:

//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);
  };
});

Fonction du fournisseur:

La fonction Provider () est l'autre moyen de créer des services. Soit nous sommes intéressés à créer un service qui affiche juste un message d'accueil à l'utilisateur. Mais nous voulons également fournir une fonctionnalité telle que l'utilisateur peut définir son propre message d'accueil. En termes techniques, nous voulons créer des services configurables. Comment peut-on le faire ? Il doit y avoir un moyen, afin que l'application puisse passer leurs messages d'accueil personnalisés et Angularjs le rendrait disponible à la fonction factory / constructor qui crée notre instance de services. Dans ce cas, la fonction provider () fait le travail. en utilisant la fonction provider () nous pouvons créer des services configurables.

Nous pouvons créer des services configurables en utilisant la syntaxe du fournisseur comme indiqué ci-dessous.

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

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

Comment fonctionne la syntaxe du fournisseur en interne?

L'objet 1.Provider est créé en utilisant la fonction constructeur que nous avons définie dans notre fonction fournisseur.

var serviceProvider = new serviceProviderConstructor();

2.La fonction que nous avons passée dans app.config (), est exécutée. C'est ce qu'on appelle la phase de configuration, et nous avons ici une chance de personnaliser notre service.

configureService(serviceProvider);

3.Finalement, l'instance de service est créée en appelant la méthode $ get de serviceProvider.

serviceInstance = serviceProvider.$get()

Exemple de code pour créer un service en utilisant la syntaxe fournie:

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 ?');
  }
);

Démonstration de travail

Résumé:


Usine utiliser une fonction d'usine qui retourne une instance de service. serviceInstance = fnFactory ();

Un service utiliser une fonction constructeur et Angular invoquer cette fonction constructeur en utilisant le mot clé 'new' pour créer l'instance de service. serviceInstance = new fnServiceConstructor ();

Fournisseur définit une fonction providerConstructor, cette fonction providerConstructor définit une fonction d'usine $ get . Angulaire appelle $ get () pour créer l'objet de service. La syntaxe du fournisseur a l'avantage supplémentaire de configurer l'objet de service avant qu'il ne soit instancié. serviceInstance = $ get ();


133
2017-11-19 13:36



Comme indiqué par plusieurs personnes ici correctement une usine, fournisseur, service, et même la valeur et la constante sont des versions de la même chose. Vous pouvez disséquer le plus général provider dans chacun d'eux. Ainsi:

enter image description here

Voici l'article de cette image:

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


79
2017-08-02 05:37



Usine

Vous donnez une fonction à AngularJS, AngularJS mettra en cache et injectera la valeur de retour lorsque l'usine est demandée.

Exemple:

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

Usage:

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

Un service

Vous donnez une fonction à AngularJS, AngularJS appellera Nouveau pour l'instancier. C'est l'instance créée par AngularJS qui sera mise en cache et injectée lorsque le service est demandé. Depuis Nouveau a été utilisé pour instancier le service, le mot-clé ce est valide et fait référence à l'instance.

Exemple:

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

Usage:

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

Fournisseur

Vous donnez une fonction à AngularJS, et AngularJS appellera sa fonction $get fonction. C'est la valeur de retour du $get fonction qui sera mise en cache et injectée lorsque le service est demandé.

Les fournisseurs vous permettent de configurer le fournisseur avant AngularJS appelle le $get méthode pour obtenir l'injectible.

Exemple:

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

Utilisation (en tant qu'injectable dans un contrôleur)

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

Utilisation (configuration du fournisseur avant $get est appelé pour créer l'injectable)

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

62
2018-05-19 19:53



J'ai remarqué quelque chose d'intéressant en jouant avec les fournisseurs.

La visibilité des injectables est différente pour les prestataires que pour les services et les usines. Si vous déclarez une "constante" AngularJS (par exemple, myApp.constant('a', 'Robert');), vous pouvez l'injecter dans les services, les usines et les fournisseurs.

Mais si vous déclarez une "valeur" AngularJS (par exemple., myApp.value('b', {name: 'Jones'});), vous pouvez l'injecter dans les services et les usines, mais PAS dans la fonction de création de fournisseur. Vous pouvez cependant l'injecter dans le $get fonction que vous définissez pour votre fournisseur. Ceci est mentionné dans la documentation d'AngularJS, mais il est facile à manquer. Vous pouvez le trouver sur la page% provide dans les sections sur la valeur et les méthodes constantes.

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>

54
2017-10-09 03:43