meaning - angularjs tutorial pdf




सेवा बनाम फैक्टरी के बारे में उलझन में (15)

जैसा कि मैं इसे समझता हूं, जब कारखाने के अंदर मैं एक वस्तु वापस करता हूं जो नियंत्रक में इंजेक्शन देता है। एक सेवा के अंदर जब मैं this वस्तु का उपयोग कर रहा हूं और कुछ भी वापस नहीं कर रहा हूं।

मैं इस धारणा के तहत था कि एक सेवा हमेशा एक सिंगलटन थी , और यह कि प्रत्येक नियंत्रक में एक नई फैक्ट्री वस्तु इंजेक्शन दी जाती है। हालांकि, जैसा कि यह पता चला है, एक कारखाना वस्तु भी एक सिंगलटन है?

उदाहरण कोड प्रदर्शित करने के लिए:

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

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

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

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

उपयोगकर्ता बदलते समय। user.first में सबसे ACtrl यह उस User को बदल BCtrl है। BCtrl सबसे पहले भी बदला जाता है, उदाहरण के लिए User एक सिंगलटन है?

मेरी धारणा यह थी कि एक कारखाने के साथ एक नियंत्रक में एक नया उदाहरण इंजेक्शन दिया गया था?


लाइव उदाहरण

"हैलो वर्ल्ड" उदाहरण

factory / service / provider :

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

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

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

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

    this.name = 'Default';

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

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

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


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

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

AngularJS सेवा बनाम फैक्टरी

module.service( 'serviceName', function );

module.factory( 'factoryName', function );

जब injectable तर्क के रूप में serviceName घोषित किया जाता है तो आपको फ़ंक्शन का एक उदाहरण प्रदान किया जाएगा। दूसरे शब्दों में नया FunctionYouPassedToService() । यह ऑब्जेक्ट उदाहरण सेवा ऑब्जेक्ट बन जाता है जो AngularJS रजिस्ट्रार करता है और यदि आवश्यक हो तो बाद में अन्य services / controllers को इंजेक्ट services / controllers है।

factoryName को एक injectable तर्क के रूप में घोषित करते समय आपको factoryName को पारित फ़ंक्शन संदर्भ का आह्वान करके लौटाया गया मान प्रदान किया जाएगा।

नीचे उदाहरण में हम MyService को दो अलग-अलग तरीकों से परिभाषित MyService हैं। ध्यान दें कि कैसे। सेवा हम इस this.methodname का उपयोग कर सेवा विधियां this.methodname । में। कारखाना हमने एक कारखाना वस्तु बनाई और इसे विधियों को सौंपा।

AngularJS। सेवा

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

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

AngularJS। फैक्टरी

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

    var factory = {}; 

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

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

    return factory;
});

एक कन्स्ट्रक्टर फ़ंक्शन को वापस करने का एक तरीका भी है ताकि आप कारखानों में नए वर्गों को वापस कर सकें, जैसे:

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

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

तो आप इसे नियंत्रक में कर सकते हैं, जो MyObjectWithParam का उपयोग करता है:

var obj = new MyObjectWithParam("hello"),

यहां पूरा उदाहरण देखें:
http://plnkr.co/edit/GKnhIN?p=preview

और यहां Google समूह पेज, जहां इसकी चर्चा हुई थी:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ


डिजाइन पैटर्न के संदर्भ में मैं उनके बीच अंतर को समझता हूं:

सेवा : एक प्रकार लौटाएं, जिसे उस प्रकार की वस्तु बनाने के लिए नया किया जाएगा। यदि जावा समानता का उपयोग किया जाता है, तो सेवा जावा क्लास परिभाषा देता है

फैक्टरी : एक ठोस वस्तु देता है जिसका तुरंत उपयोग किया जा सकता है। जावा एनालॉजी में एक फैक्टरी एक जावा ऑब्जेक्ट देता है।

वह हिस्सा जो अक्सर लोगों (स्वयं सहित) को भ्रमित करता है वह यह है कि जब आप अपने कोड में एक सेवा या फैक्ट्री इंजेक्ट करते हैं तो उनका उपयोग उसी तरह किया जा सकता है, जो आप दोनों मामलों में अपने कोड में प्राप्त करते हैं वह एक ठोस वस्तु है जिसे आप तुरंत बुला सकते हैं। सेवा के मामले में जिसका मतलब है, कोणीय आपके द्वारा सेवा घोषणा पर "नया" कॉल करता है। मुझे लगता है कि यह एक जटिल अवधारणा है।


प्राथमिक अंतर यहां दिए गए हैं:

सेवाएं

सिंटेक्स: module.service( 'serviceName', function );

परिणाम: जब सेवा नाम को इंजेक्शन योग्य तर्क के रूप में घोषित किया जाता है तो आपको module.service . module.service को module.service गए फ़ंक्शन के उदाहरण के साथ प्रदान किया जाएगा।

उपयोग: उपयोगिता कार्यों को साझा करने के लिए उपयोगी हो सकता है जो इंजेक्शन फ़ंक्शन संदर्भ में बस () को जोड़कर आमंत्रित करने के लिए उपयोगी हैं। injectedArg.call( this ) या इसी तरह के साथ भी चलाया जा सकता है।

कारखाना

सिंटेक्स: module.factory( 'factoryName', function );

परिणाम: फैक्ट्रीनाम को इंजेक्शन योग्य तर्क के रूप में घोषित करते समय आपको मॉड्यूल.फैक्टरी को पारित फ़ंक्शन संदर्भ का आह्वान करके लौटाया जाने वाला मान प्रदान किया जाएगा।

उपयोग: 'वर्ग' फ़ंक्शन को वापस करने के लिए उपयोगी हो सकता है जिसे उदाहरण बनाने के लिए नया किया जा सकता है।

सेवा बनाम फैक्ट्री के बारे में उलझन में स्टैक ओवरफ्लो पर एंगुलरजेएस दस्तावेज और इसी तरह के प्रश्न की भी जांच करें।

सेवाओं और कारखाने का उपयोग कर उदाहरण यहां दिया गया है। AngularJS सेवा बनाम कारखाने के बारे में और पढ़ें।


बहुत सरलता से:

। सेवा - पंजीकृत फ़ंक्शन को कन्स्ट्रक्टर के रूप में बुलाया जाएगा (उर्फ 'नया')

। फैक्टरी - पंजीकृत फ़ंक्शन को एक साधारण फ़ंक्शन के रूप में बुलाया जाएगा

दोनों एक बार आते हैं जिसके परिणामस्वरूप सिंगलटन ऑब्जेक्ट होता है जो आपके ऐप के अन्य घटकों में इंजेक्शन दिया जाता है।


मेरे लिए प्रकाशन तब आया जब मुझे एहसास हुआ कि वे सभी एक ही तरीके से काम करते हैं: एक बार कुछ चलकर , उन्हें प्राप्त मूल्य को संग्रहित करके, और फिर निर्भरता इंजेक्शन के माध्यम से संदर्भित होने पर उसी संग्रहित मूल्य को खांसी दें।

कहो हमारे पास है:

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

तीनों के बीच का अंतर यह है कि:

  1. a संग्रहित मूल्य fn चलने से आता है, दूसरे शब्दों में: fn()
  2. b का संग्रहीत मूल्य new आईएनजी fn से आता है, दूसरे शब्दों में: new fn()
  3. c का संग्रहीत मूल्य पहले new आईएनजी fn द्वारा एक उदाहरण प्राप्त करने से आता है, और उसके बाद उदाहरण की एक $get विधि $get रहा है

जिसका अर्थ है, कोणीय के अंदर कैश ऑब्जेक्ट की तरह कुछ है, जिसका प्रत्येक इंजेक्शन का मूल्य केवल एक बार असाइन किया जाता है, जब उन्हें पहली बार इंजेक्शन दिया जाता है, और कहां:

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

यही कारण है कि हम सेवाओं में इसका उपयोग this हैं, और इसे परिभाषित this.$get प्रदाताओं में this.$get है।

उम्मीद है की यह मदद करेगा।


यहां सेवाओं के बनाम कारखानों के कुछ और उदाहरण दिए गए हैं जो उनके बीच अंतर देखने में उपयोगी हो सकते हैं। असल में, एक सेवा में "नया ..." कहा जाता है, यह पहले से ही तत्काल है। एक कारखाना स्वचालित रूप से तत्काल नहीं है।

मूल उदाहरण

एक क्लास ऑब्जेक्ट लौटाएं जिसमें एक विधि है

यहां एक ऐसी सेवा है जिसमें एक विधि है:

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

यहां एक कारखाना है जो किसी ऑब्जेक्ट को विधि के साथ देता है:

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

एक मूल्य वापस करें

एक कारखाना जो संख्याओं की एक सूची देता है:

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

console.log(NumberListFactory);

एक सेवा जो संख्याओं की एक सूची देता है:

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

console.log(NumberLister.numbers);

दोनों मामलों में उत्पादन समान है, संख्याओं की सूची।

उन्नत उदाहरण

कारखानों का उपयोग कर "वर्ग" चर

इस उदाहरण में हम काउंटर फैक्ट्री को परिभाषित करते हैं, यह काउंटर में वृद्धि या कमी करता है और आप वर्तमान गिनती प्राप्त कर सकते हैं या प्राप्त कर सकते हैं कि कितने काउंटर फैक्ट्री ऑब्जेक्ट्स बनाए गए हैं:

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

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

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

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

})

हम कई काउंटर बनाने के लिए काउंटर CounterFactory का उपयोग करते हैं। हम क्लास वैरिएबल तक पहुंच सकते हैं यह देखने के लिए कि कितने काउंटर बनाए गए थे:

var people_counter;
var places_counter;

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

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

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

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

इस कोड का आउटपुट है:

people 0
people 1
counters 1
places 0
counters 2
counters 2

सेवा बनाम फैक्टरी बनाम प्रदाता को समझने के लिए यह सबसे अच्छा और संक्षिप्त जवाब होगा

स्रोत : https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/HuZsOsMvKv4J

डेमो jsbin साथ बेन क्या कहता है

"प्राथमिक मतभेदों को चित्रित करने वाले कोड में टिप्पणियां हैं लेकिन मैं उन पर थोड़ा सा विस्तार करूंगा। एक नोट के रूप में, मैं बस इसके चारों ओर अपना सिर प्राप्त कर रहा हूं इसलिए यदि मैं कुछ गलत कहता हूं तो कृपया मुझे बताएं।

सेवाएं

सिंटेक्स : module.service ('serviceName', फ़ंक्शन);

परिणाम : जब सेवा नाम को इंजेक्शन योग्य तर्क के रूप में घोषित किया जाता है तो आपको मॉड्यूल.service को पारित वास्तविक फ़ंक्शन संदर्भ प्रदान किया जाएगा।

उपयोग : उपयोगिता कार्यों को साझा करने के लिए उपयोगी हो सकता है जो इंजेक्शन फ़ंक्शन संदर्भ में बस () को जोड़कर आमंत्रित करने के लिए उपयोगी हैं। इंजेक्शन Arg.call (यह) या इसी तरह के साथ भी चलाया जा सकता है।

कारखाना

सिंटेक्स : module.factory ('factoryName', फ़ंक्शन);

परिणाम : फैक्ट्रीनाम को इंजेक्शन योग्य तर्क के रूप में घोषित करते समय आपको मॉड्यूल.फैक्टरी को पारित फ़ंक्शन संदर्भ का आह्वान करके लौटाया जाने वाला मान प्रदान किया जाएगा।

उपयोग : 'वर्ग' फ़ंक्शन को वापस करने के लिए उपयोगी हो सकता है जिसे उदाहरण बनाने के लिए नया किया जा सकता है।

प्रदाताओं

सिंटेक्स : module.provider ('प्रदाता नाम', फ़ंक्शन);

परिणाम : जब प्रदाता नाम को इंजेक्शन योग्य तर्क के रूप में घोषित किया जाता है तो आपको मॉड्यूल.प्रोवाइडर को पास किए गए फ़ंक्शन संदर्भ की $ प्राप्त विधि का आह्वान करके लौटाया जाने वाला मान प्रदान किया जाएगा।

उपयोग : 'वर्ग' फ़ंक्शन को वापस करने के लिए उपयोगी हो सकता है जिसे बाद में उदाहरण बनाने के लिए नया किया जा सकता है लेकिन इंजेक्शन से पहले किसी प्रकार की कॉन्फ़िगरेशन की आवश्यकता होती है। शायद उन वर्गों के लिए उपयोगी जो परियोजनाओं में पुन: प्रयोज्य हैं? इस पर अभी भी आलसी है। "बेन


हम इस तरह की एक सेवा परिभाषित कर सकते हैं:

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

.service() हमारे मॉड्यूल पर एक विधि है जो एक नाम और एक फ़ंक्शन लेती है जो सेवा को परिभाषित करती है। बहुत सीधा। एक बार परिभाषित होने के बाद, हम अन्य घटकों, जैसे नियंत्रकों, निर्देशों और फ़िल्टरों में उस विशेष सेवा को इंजेक्ट और उपयोग कर सकते हैं:

अब कारखाने के समान ही बात:

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

फिर,। .factory() हमारे मॉड्यूल पर एक विधि है और यह एक नाम और एक समारोह भी लेता है, जो फैक्ट्री को परिभाषित करता है। हम इंजेक्ट कर सकते हैं और उस चीज़ का बिल्कुल उसी तरह उपयोग कर सकते हैं जैसा हमने सेवा के साथ किया था। अब यहाँ क्या अंतर है?

खैर, आप देख सकते हैं कि फैक्ट्री में इसके साथ काम करने की बजाए, हम एक ऑब्जेक्ट शाब्दिक लौट रहे हैं। ऐसा क्यों है? यह पता चला है, एक सेवा एक कन्स्ट्रक्टर समारोह है जबकि एक कारखाना नहीं है। इस कोणीय दुनिया के कहीं और गहरे अंदर, यह कोड है जो ऑब्जेक्ट.क्रेट () को सेवा कन्स्ट्रक्टर फ़ंक्शन के साथ कॉल करता है, जब इसे तुरंत चालू किया जाता है। हालांकि, एक कारखाना समारोह वास्तव में केवल एक समारोह है जिसे बुलाया जाता है, यही कारण है कि हमें एक वस्तु को स्पष्ट रूप से वापस करना होगा।


सभी कोणीय सेवाएं सिंगलेट हैं :

डॉक्स ( सिंगलेट्स के रूप में सेवाएं देखें): https://docs.angularjs.org/guide/services

अंत में, यह जानना महत्वपूर्ण है कि सभी कोणीय सेवाएं एप्लिकेशन सिंगलेट हैं। इसका मतलब है कि प्रति इंजेक्टर द्वारा दी गई सेवा का केवल एक उदाहरण है।

मूल रूप से सेवा और कारखाने के बीच का अंतर निम्नानुसार है:

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

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

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

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

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

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

इस प्रस्तुति को $ प्रदान करने के बारे में http://slides.wesalvaro.com/20121113/#/ : http://slides.wesalvaro.com/20121113/#/

उन स्लाइड्स का उपयोग AngularJs मीटिंग्स में से एक में किया गया था: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html


सेवा शैली: ( शायद सबसे सरल एक ) वास्तविक फ़ंक्शन देता है: उपयोगिता फ़ंक्शंस साझा करने के लिए उपयोगी जो इंजेक्शन फ़ंक्शन संदर्भ में बस जोड़कर () को आमंत्रित करने के लिए उपयोगी हैं।

AngularJS में एक सेवा एक सिंगलटन जावास्क्रिप्ट ऑब्जेक्ट है जिसमें फ़ंक्शंस का एक सेट होता है

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

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

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

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

    myService.doIt();

});

फैक्टरी शैली: ( अधिक शामिल लेकिन अधिक परिष्कृत ) फ़ंक्शन का रिटर्न मान देता है: जावा में नए ऑब्जेक्ट () जैसे ऑब्जेक्ट को तुरंत चालू करें।

फैक्टरी एक ऐसा कार्य है जो मूल्य बनाता है। जब एक सेवा, नियंत्रक इत्यादि को कारखाने से इंजेक्शन दिया जाता है, तो फैक्ट्री मांग पर मूल्य बनाती है। एक बार बनाया गया, मूल्य सभी सेवाओं, नियंत्रकों आदि के लिए पुन: उपयोग किया जाता है, जिन्हें इंजेक्शन की आवश्यकता होती है।

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

myModule.value("numberValue", 999);

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

    console.log(myFactory);

});

प्रदाता शैली: ( पूर्ण उड़ा, कॉन्फ़िगर करने योग्य संस्करण ) फ़ंक्शन के $ फ़ंक्शन फ़ंक्शन का आउटपुट देता है: कॉन्फ़िगर करने योग्य।

AngularJS में प्रदाता कारखाने का सबसे लचीला रूप है जिसे आप बना सकते हैं। आप एक प्रदाता को एक मॉड्यूल के साथ पंजीकृत करते हैं जैसे कि आप किसी सेवा या फैक्ट्री के साथ करते हैं, सिवाय इसके कि आप प्रदाता () फ़ंक्शन का उपयोग करते हैं।

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

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

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

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

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

        return service;
    }

    return provider;
});

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

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

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

});

src jenkov

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

jsbin

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

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

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

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

    this.name = 'Default';

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

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

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

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

</body>
</html>

jsfiddle


There are three ways of handling business logic in AngularJS: ( Inspired by Yaakov's Coursera AngularJS course ) which are:

  1. सर्विस
  2. फ़ैक्टरी
  3. Provider

Here we are only going to talk about Service vs Factory

SERVICE :

Syntax:

app.js

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

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

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

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

index.html

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

The main features of Service:

  1. Lazily Instantiated : If the service is not injected it won't be instantiated ever. So to use it you will have to inject it to a module.

  2. Singleton : If it is injected to multiple modules, all will have access to only one particular instance. That is why, it is very convenient to share data across different controllers.

FACTORY

Now let's talk about the Factory in AngularJS

First let's have a look at the syntax :

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

Now using the above two in the controller:

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

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

Features of Factory:

  1. This types of services follow the factory design pattern . The factory can be thought of as a central place that creates new objects or methods.

  2. This does not only produce singleton, but also customizable services.

  3. The .service() method is a factory that always produces the same type of service, which is a singleton. There is no easy way to configure it's behavior. That .service() method is usually used as a shortcut for something that doesn't require any configuration whatsoever.


This is what helped me to understand the difference, thanks to a blog post by Pascal Precht.

A service is a method on a module that takes a name and a function that defines the service. You can inject and use that particular service in other components, like controllers, directives and filters. A factory is a method on a module and it also takes a name and a function, that defines the factory. We can also inject and use the it same way we did with the service.

Objects created with new use the value of the prototype property of their constructor function as their prototype, so I found the Angular code that calls Object.create(), that I believe is the service constructor function when it gets instantiated. However, a factory function is really just a function that gets called, which is why we have to return an object literal for the factory.

Here is the angular 1.5 code I found for factory:

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

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

Angular source code snippet for the factory() function:

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

It takes the name and the factory function that is passed and returns a provider with the same name, that has a $get method which is our factory function. Whenever you ask the injector for a specific dependency, it basically asks the corresponding provider for an instance of that service, by calling the $get() method. That's why $get() is required, when creating providers.

Here is the angular 1.5 code for service.

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

It turns out that when we call service(), it actually calls factory()! However, it doesn't just pass our service constructor function to the factory as is. It also passes a function that asks the injector to instantiate an object by the given constructor.

In other words, if we inject MyService somewhere, what happens in the code is:

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

To restate it again, a service calls a factory, which is a $get() method on the corresponding provider. Moreover, $injector.instantiate() is the method that ultimately calls Object.create() with the constructor function. That's why we use "this" in services.

For ES5 it doesn't matter which we use: service() or factory(), it's always a factory that is called which creates a provider for our service.

You can do the exact same thing with services as well though. A service is a constructor function, however, that doesn't prevent us from returning object literals. So we can take our service code and write it in a way that it basically does the exact same thing as our factory or in other words, you can write a service as a factory to return an object.

Why do most people recommend to use factories over services? This is the best answer I've seen which comes from Pawel Kozlowski's book: Mastering Web Application Development with AngularJS.

The factory method is the most common way of getting objects into AngularJS dependency injection system. It is very flexible and can contain sophisticated creation logic. Since factories are regular functions, we can also take advantage of a new lexical scope to simulate "private" variables. This is very useful as we can hide implementation details of a given service."


  • With the factory you actually create an object inside of the factory and return it.
  • With the service you just have a standard function that uses the this keyword to define function.
  • With the provider there's a $get you define and it can be used to get the object that returns the data.




angularjs