简体   繁体   中英

Why are Factories more flexible than Services in AngularJS?

According to this source ,

Why do the two styles exist if they can accomplish the same thing? Factories offer slightly more flexibility than services because they can return functions which can then be new'd. This follows the factory pattern from object oriented programming. A factory can be an object for creating other objects.

I'm having trouble connecting this piece of information to the concept of constructors in Javascript and object / prototype. Can someone help me connect the dot? Thanks.

Service VS Factory

A service is a constructor function that can be called with 'new' where as a factory returns an object that you may run some code before that is why it is more flexible.

To see a detailed example please check out this question. matys84pl talks about it in detail.

Factory

These are practically singletons. So for instance you can hold data across calls to it.

factory('myFactory', function () {
   var internalList = [];

   return {
       add: function (value) { internalList.push(value); },
       get: function () { return internalList; }
   }
});

As you could imagine, if controller1 pushed Hi into the list and controller2 called get() immediately after, it would recieve [ 'Hi' ] .

Service

From the angular docs

JavaScript developers often use custom types to write object-oriented code.

service('UnicornLauncher', function (apiToken) {

  this.launchedCount = 0;
  this.launch = function() {
    // Make a request to the remote API and include the apiToken
    ...
    this.launchedCount++;
  }
});

Provider

For some bonus reading, I'll tell you about a provider. A provider wraps a factory . Why? Because there are two phases in an angular application, the configure phase and the run phase. Services, factories and values AREN'T available during the run phase.

So, say we need to configure a service before it is injected into the controllers. We need to use a provider .

The angular docs have a nice example:

provider('unicornLauncher', function UnicornLauncherProvider() {
  var useTinfoilShielding = false;

  this.useTinfoilShielding = function(value) {
    useTinfoilShielding = !!value;
  };

  this.$get = ["apiToken", function unicornLauncherFactory(apiToken) {

    // let's assume that the UnicornLauncher constructor was also changed to
    // accept and use the useTinfoilShielding argument
    return new UnicornLauncher(apiToken, useTinfoilShielding);
  }];
});

so this.$get is basically the second argument of the factory('...', ... .

So if we use this in the configure phase we do this:

config(["unicornLauncherProvider", function(unicornLauncherProvider) {
  unicornLauncherProvider.useTinfoilShielding(true);
}]);

Notice how we ask for unicornLauncherProvider , we add that Provider suffix. Yet when we named our provider we didn't supply it. That is because angular automatically adds the suffix for you. If you want to access the service this provider creates, ask for the unicornLauncher .

I had an 'Eureka effect' when i realized that service & factory are only syntactic sugar for provider ( https://docs.angularjs.org/api/auto/service/ $provide#provider)

The only difference between these two is the way Angular processes the passed value before providing it with the injector. When I get the object from the injector, I usually can't tell if it has been created using a service or a factory (or any of the other $provide methods)

So the Question is "How do I want to implement this?" and not "How do I want to use this?".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM