angular.service vs angular.factory


1065

मैंने दोनों को देखा है angular.factory () और angular.service () सेवाओं की घोषणा करने के लिए; हालाँकि, मैं आधिकारिक दस्तावेज में कहीं भी नहीं मिल angular.service सकता।

दोनों विधियों में क्या अंतर है?
किसके लिए इस्तेमाल किया जाना चाहिए (यह मानते हुए कि वे अलग-अलग काम करते हैं)?



4
मैंने "[एंगुलरज] सर्विस फैक्ट्री" की खोज की, लेकिन मुझे यह भी याद था कि इसके बारे में पहले से ही एक सवाल था (क्योंकि मैंने लिखने के बारे में सोचा था / एक बिंदु पर यह सवाल)।
मार्क राजकॉक

2
एक खोज में, वर्ग-कोष्ठक एक टैग को दर्शाता है?
जाकोब

11
@ जैकोब स्क्वायर ब्रैकेट आपकी खोज को कम कर रहे हैं। [angularjs] निर्देश - angularjs के साथ पहले से टैग किए गए प्रश्नों के लिए 'निर्देशों' की खोज करेंगे।
महबूब

1
@ महबूब दूसरे शब्दों में, "हाँ" :)
ब्रायन

जवाबों:


1268
  angular.service('myService', myServiceFunction);
  angular.factory('myFactory', myFactoryFunction);

जब तक मैं इस तरह से अपने आप को इस अवधारणा के चारों ओर अपना सिर लपेटने में परेशानी नहीं हुई:

सेवा : आपके द्वारा लिखा गया कार्य नया- होगा :

  myInjectedService  <----  new myServiceFunction()

फ़ैक्टरी : आपके द्वारा लिखे जाने वाले फ़ंक्शन (निर्माता) को आमंत्रित किया जाएगा :

  myInjectedFactory  <---  myFactoryFunction()

आप जो करते हैं, वह आपके ऊपर है, लेकिन कुछ उपयोगी पैटर्न हैं ...

जैसे सार्वजनिक एपीआई को उजागर करने के लिए एक सेवा समारोह लिखना :

function myServiceFunction() {
  this.awesomeApi = function(optional) {
    // calculate some stuff
    return awesomeListOfValues;
  }
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.awesome = myInjectedService.awesomeApi();

या किसी सार्वजनिक API को बेनकाब करने के लिए किसी फ़ैक्टरी फ़ंक्शन का उपयोग करना :

function myFactoryFunction() {
  var aPrivateVariable = "yay";

  function hello() {
    return "hello mars " + aPrivateVariable;
  }

  // expose a public API
  return {
    hello: hello
  };
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.hello = myInjectedFactory.hello();

या एक निर्माता को वापस करने के लिए एक फैक्ट्री फ़ंक्शन का उपयोग करना :

function myFactoryFunction() {
    return function() {
        var a = 2;
        this.a2 = function() {
            return a*2;
        };
    };
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();

कौन सा उपयोग करना है? ...

आप दोनों के साथ एक ही बात को पूरा कर सकते हैं। हालांकि, कुछ मामलों में फैक्टरी आपको सरल सिंटैक्स के साथ इंजेक्शन बनाने के लिए थोड़ा अधिक लचीलापन देता है। ऐसा इसलिए है क्योंकि myInjectedService को हमेशा एक ऑब्जेक्ट होना चाहिए, myInjectedFactory एक ऑब्जेक्ट, एक फ़ंक्शन संदर्भ या सभी पर कोई मूल्य हो सकता है। उदाहरण के लिए, यदि आपने कंस्ट्रक्टर बनाने के लिए एक सेवा लिखी है (जैसा कि ऊपर दिए गए अंतिम उदाहरण में है), तो यह तत्काल होना होगा जैसे:

var myShinyNewObject = new myInjectedService.myFunction()

जो यकीनन इससे कम वांछनीय है:

var myShinyNewObject = new myInjectedFactory();

(लेकिन आपको पहले स्थान पर इस तरह के पैटर्न का उपयोग करने के बारे में सावधान रहना चाहिए क्योंकि आपके नियंत्रकों में नई-नई वस्तुएं कठिन-से-निर्भर निर्भरता पैदा करती हैं जो परीक्षण के लिए नकली होना मुश्किल है। बेहतर सेवा के लिए वस्तुओं के संग्रह का प्रबंधन करना बेहतर है। आप new()विली-निली का उपयोग करें ।)


एक बात और, वे सभी सिंगलेट्स हैं ...

यह भी ध्यान रखें कि दोनों मामलों में, कोणीय आपको एक सिंगलटन का प्रबंधन करने में मदद कर रहा है। भले ही आप अपनी सेवा या फ़ंक्शन को कितनी बार या कितनी बार इंजेक्ट करते हैं, आपको एक ही ऑब्जेक्ट या फ़ंक्शन के लिए एक ही संदर्भ मिलेगा। (अपवाद के साथ जब कोई कारखाना बस एक संख्या या स्ट्रिंग की तरह एक मूल्य लौटाता है। उस स्थिति में, आपको हमेशा एक ही मूल्य मिलेगा, लेकिन एक संदर्भ नहीं।)


2
क्या इसे न्यूटेबल की तुलना में ऑब्जेक्ट कंस्ट्रक्टर कहना बेहतर होगा?
मार्कशीट

2
@ ह्यूगो, मैं यह प्रदर्शित कर रहा था कि आप दोनों के साथ एक ही बात को प्रभावी ढंग से पूरा कर सकते हैं, यह सिर्फ इतना है कि वाक्यविन्यास अलग होगा।
गिल बिरमन

105
मुझे यकीन नहीं है कि सेवा और कारखाने के बीच अंतर के बारे में मुझे कितनी बार पढ़ना होगा, इससे पहले कि मैं आश्वस्त हो
जाऊं

10
हमारे पास पहले से ही "नया" कहने के लिए एक क्रिया है, यह "तत्काल" है। सिर्फ संदर्भ के लिए। :)
sscarduzio

7
फैक्ट्रीज़ ऐसे फ़ंक्शंस हैं, जिन्हें इनवॉइस किया जाता है, ताकि वे कुछ भी वापस कर सकें। दूसरी ओर, सेवाओं को कोणीय द्वारा त्वरित किया जाता है new fn(), इसलिए उन्हें एक उदाहरण वापस करना होगा।
गिल बिरमान

318

सीधे शब्दों में कहें ..

// Service
service = (a, b) => {
  a.lastName = b;
  return a;
};

// Factory
factory = (a, b) => Object.assign({}, a, { lastName: b });

const fullName = { firstName: 'john' };

// Service
const lastNameService = (a, b) => {
  a.lastName = b;
  return a;
};
console.log(lastNameService(fullName, 'doe'));

// Factory
const lastNameFactory = (a, b) => 
  Object.assign({}, a, { lastName: b })
console.log(lastNameFactory(fullName, 'doe'));


169
यार, शुक्रिया। ऐसा नहीं है कि अन्य उत्तरों का विवरण मान्य नहीं है, लेकिन कुछ बार आपको 10 सेकंड संस्करण की आवश्यकता होती है।
आर क्लेवेन

4
बस सेवा समारोह में कुछ भी नहीं है। This.name = ... पता चलता है कि यह एक एपीआई उजागर कर रहा है पर्याप्त है।
24

3
हालांकि अगर आप रिटर्न और ऑब्जेक्ट करते हैं तो वह इसके बजाय इसका उपयोग करेगा। jsfiddle.net/Ne5P8/1221
MrB

@MrB, यह एक सामान्य जावास्क्रिप्ट सुविधा है, जो कोणीय या इस प्रश्न के संदर्भ के लिए विशिष्ट नहीं है।
ओम शंकर

@ ओएम शंकर, ऊपर दिया गया उत्तर दिखा रहा है कि अंतर इस बनाम एक लौटी हुई वस्तु का उपयोग है। मैं दिखा रहा था कि "THIS" एक डिफ़ॉल्ट मान है जो किसी सेवा के साथ उपयोग किया जाएगा, लेकिन यदि आप एक मूल्य वापस करते हैं तो यह लगभग एक कारखाने की तरह कार्य करेगा। हालाँकि, दूसरी तरफ एक फ़ैक्टरी को लौटाए गए मान की आवश्यकता प्रतीत होती है, अन्यथा एक त्रुटि होगी - (इस उदाहरण में दिखाया गया है - jsfiddle.net/hmoc0q3v/1 )।
MrB

247

यहाँ प्राथमिक अंतर हैं:

सेवाएं

वाक्य - विन्यास: module.service( 'serviceName', function );

परिणाम: जब एक इंजेक्शन तर्क आप के साथ उपलब्ध कराया जाएगा के रूप में SERVICENAME की घोषणा एक समारोह के कहने के लिए पारित किया module.service

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

कारखाना

वाक्य - विन्यास: module.factory( 'factoryName', function );

परिणाम: जब कारखानेनाम को एक इंजेक्शन तर्क के रूप में घोषित किया जाता है, तो आपको उस मान के साथ प्रदान किया जाएगा जो फ़ंक्शन संदर्भ को पारित करके लौटाया जाता है module.factory

उपयोग: एक 'क्लास' फ़ंक्शन को लौटाने के लिए उपयोगी हो सकता है जो तब इंस्टेंस बनाने के लिए नया हो सकता है।

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

आप AngularJS प्रलेखन और सेवा बनाम फैक्ट्री के बारे में पूछे जाने वाले स्टैकओवरफ़्लो पर समान प्रश्न भी देख सकते हैं ।


27
मैं एक कारखाने के आपके उदाहरण उपयोग से असहमत हूं। दोनों सेवाओं और कारखानों (एक समारोह मान लिया गया है। यह सिर्फ एक मूल्य या एक वस्तु हो सकता है) new'ed हो सकता है। वास्तव में एक सेवा एकमात्र विकल्प है जो नए होने की गारंटी है क्योंकि आपको एक फ़ंक्शन उदाहरण प्रदान किया जाता है। मैं कहूंगा कि किसी सेवा पर एक कारखाने का उपयोग करने का लाभ यह है कि यह गुणों तक पहुंच पर कुछ नियंत्रण की अनुमति देता है - निजी और सार्वजनिक प्रति सेगमेंट जबकि सेवा के सभी गुण प्रकृति द्वारा उजागर होते हैं। और मुझे लगता है कि एक प्रदाता एक कारखाने के एक कारखाने के रूप में - केवल यह विन्यास योग्य है और विन्यास समय पर विन्यास योग्य है।
ड्रू आर

1
@DrewR आपकी टिप्पणी के लिए धन्यवाद, मुझे एक कारखाने का उपयोग करके सार्वजनिक और निजी तरीकों का एक अच्छा उदाहरण मिला: stackoverflow.com/a/14904891/65025
edzillion

मुझे इस पर, वास्तव में @ ड्र्यू से सहमत होना होगा। मैंने पहले वस्तुओं को वापस करने के लिए कारखानों का उपयोग किया है, लेकिन इस बिंदु पर ईमानदारी से यह $providersहर समय उपयोग करने के लिए इसके लायक हो सकता है ।
jedd.ahyoung

सेवा, कंस्ट्रक्टर को स्वचालित रूप से त्वरित करने की है?
Martian2049

1
@ ड्रयू - मेरी समझ से, यह सच है कि आप सेवा से उसी नए प्रभाव को प्राप्त कर सकते हैं जैसे आप किसी कारखाने में कर सकते हैं, लेकिन यह उसके लिए नहीं है। यह मुख्य लक्ष्य है जब आप बस कुछ उपयोगिता वस्तु वापस करना चाहते हैं और इसके लिए यह एक अधिक उपयुक्त वाक्यविन्यास प्रदान करता है - आप बस this.myFunc = function(){}अपनी सेवा में लिख सकते हैं (ऑब्जेक्ट को बनाने के लिए कोड लिखने से बचाता है जैसे आपको एक कारखाने के साथ करना होगा )।
बोर्नटोडकोड

137

TL; DR

1) जब आप किसी फैक्ट्री का उपयोग कर रहे होते हैं तो आप एक ऑब्जेक्ट बनाते हैं, उसमें गुण जोड़ते हैं, फिर उसी ऑब्जेक्ट को वापस करते हैं। जब आप इस कारखाने को अपने नियंत्रक में पास करते हैं, तो ऑब्जेक्ट पर मौजूद गुण अब आपके कारखाने के माध्यम से उस नियंत्रक में उपलब्ध होंगे।

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) जब आप सेवा का उपयोग कर रहे होते हैं , तो कोणीय उसे 'नए' कीवर्ड वाले दृश्यों के पीछे कर देता है। उसके कारण, आप 'इस' में गुण जोड़ेंगे और सेवा 'यह' वापस आ जाएगी। जब आप सेवा को अपने नियंत्रक में पास करते हैं, तो 'यह' पर वे गुण अब आपकी सेवा के माध्यम से उस नियंत्रक पर उपलब्ध होंगे।

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

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



गैर टीएल, डॉ

1) फैक्ट्री
फैक्ट्री किसी सेवा को बनाने और कॉन्फ़िगर करने का सबसे लोकप्रिय तरीका है। वास्तव में टीएल से बहुत अधिक नहीं है; डीआर ने कहा। आप बस एक ऑब्जेक्ट बनाते हैं, उसमें गुण जोड़ते हैं, फिर उसी ऑब्जेक्ट को वापस करते हैं। फिर जब आप कारखाने को अपने नियंत्रक में पास करते हैं, तो ऑब्जेक्ट पर मौजूद गुण अब आपके कारखाने के माध्यम से उस नियंत्रक में उपलब्ध होंगे। एक अधिक व्यापक उदाहरण नीचे है।

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

अब हम जो भी गुण us सेवा ’से जोड़ते हैं, वह हमारे लिए तब उपलब्ध होगा जब हम '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;
});

यहाँ आप देखेंगे कि हम उन चर / फ़ंक्शन को 'सेवा' में संलग्न नहीं कर रहे हैं। हम उन्हें केवल उपयोग करने या बाद में संशोधित करने के लिए बना रहे हैं।

  • बेस यूआरएल वह आधार URL है जो आईट्यून्स एपीआई की आवश्यकता होती है
  • _artist वह कलाकार है जिसे हम देखना चाहते हैं
  • _finalUrl एक अंतिम और पूरी तरह से निर्मित URL है जिससे हम आईट्यून्स को कॉल करेंगे MakeUrl एक ऐसा फंक्शन है जो हमारे आईट्यून्स फ्रेंडली URL को बनाएगा और वापस करेगा।

अब जबकि हमारे सहायक / निजी चर और कार्य स्थान पर हैं, तो आइए कुछ गुणों को 'सेवा' ऑब्जेक्ट में जोड़ें। हम जो कुछ भी 'सेवा' में डालते हैं, हम सीधे 'myFactory' में पास करने वाले नियंत्रक में उपयोग करने में सक्षम होंगे।

हम सेटआर्टिस्ट और गेटआर्टिस्ट तरीके बनाने जा रहे हैं जो बस कलाकार को लौटाते हैं या सेट करते हैं। हम एक ऐसी विधि भी बनाने जा रहे हैं जो हमारे बनाए गए URL के साथ iTunes API को कॉल करेगी। यह विधि एक वादा वापस करने जा रही है जो आइट्यून्स एपीआई से डेटा वापस आने के बाद पूरा होगा। यदि आपके पास कोणीय में वादों का उपयोग करने का अधिक अनुभव नहीं है, तो मैं उन पर एक गहरा गोता लगाने की सलाह देता हूं।

नीचे setArtist आप कलाकार स्थापित करने के लिए एक कलाकार स्वीकार करता है और अनुमति देता है। getArtist कलाकार callItunes को पहले कॉल करता है makeUrl () उस URL को बनाने के लिए जिसे हम अपने $ http अनुरोध के साथ उपयोग करेंगे। फिर यह एक वादा वस्तु सेट करता है, हमारे अंतिम url के साथ $ http अनुरोध करता है, फिर क्योंकि $ http एक वादा वापस करता है, हम हमारे अनुरोध के बाद .suor या .error को कॉल करने में सक्षम हैं। फिर हम आईट्यून्स डेटा के साथ अपने वादे को हल करते हैं, या हम इसे एक संदेश के साथ अस्वीकार करते हुए कहते हैं कि 'एक त्रुटि थी'।

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' सेवा में इंजेक्शन लगा रहे हैं। फिर हम अपने $ स्कोप ऑब्जेक्ट पर गुण सेट करते हैं जो 'myFactory' के डेटा से आते हैं। ऊपर केवल ट्रिकी कोड है यदि आपने पहले कभी वादों को निपटाया नहीं है। क्योंकि callItunes एक वादा वापस कर रहा है, हम .then () विधि का उपयोग करने में सक्षम हैं और केवल एक बार हमारा स्कोप iTunes डेटा के साथ पूरा होने पर $ गुंजाइश.data.artistData सेट करते हैं। आप देखेंगे कि हमारा नियंत्रक बहुत 'पतला' है। हमारे सभी तर्क और निरंतर डेटा हमारी सेवा में स्थित हैं, हमारे नियंत्रक में नहीं।

2) सेवा
किसी सेवा को बनाते समय यह जानना सबसे बड़ी बात है कि यह 'नए' कीवर्ड के साथ त्वरित है। आपके लिए जावास्क्रिप्ट गुरु यह आपको कोड की प्रकृति में एक बड़ा संकेत देना चाहिए। आपके लिए जावास्क्रिप्ट में एक सीमित पृष्ठभूमि के साथ या उन लोगों के लिए जो वास्तव में 'नया' कीवर्ड से परिचित नहीं हैं, आइए कुछ जावास्क्रिप्ट बुनियादी बातों की समीक्षा करें जो अंततः एक सेवा की प्रकृति को समझने में हमारी मदद करेंगे।

जब आप किसी फ़ंक्शन को 'नए' कीवर्ड से जोड़ते हैं, तो वास्तव में एक फ़ंक्शन बनाते हैं और 'नए' कीवर्ड के साथ इसे लागू करते हैं, तो चलिए देखते हैं कि इंटरप्रेटर क्या करता है जब वह 'नया' कीवर्ड देखता है। अंतिम परिणाम दोनों समान होंगे।

पहले हम अपना कंस्ट्रक्टर बनाएं।

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

यह एक विशिष्ट जावास्क्रिप्ट कंस्ट्रक्टर फ़ंक्शन है। अब जब भी हम 'नया' कीवर्ड का उपयोग करके व्यक्ति फ़ंक्शन को आमंत्रित करते हैं, तो 'यह' नए बनाए गए ऑब्जेक्ट के लिए बाध्य होगा।

अब हम अपने व्यक्ति के प्रोटोटाइप पर एक विधि जोड़ते हैं ताकि यह हमारे व्यक्ति 'वर्ग' के हर उदाहरण पर उपलब्ध होगा।

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

अब, क्योंकि हम प्रोटोटाइप पर SayName फ़ंक्शन डालते हैं, इसलिए पर्सन का हर इंस्टेंस, उस नाम के नाम से क्रम अलर्ट में SayName फ़ंक्शन को कॉल करने में सक्षम होगा।

अब जब हमारे पास हमारा व्यक्ति निर्माण कार्य है और इसके प्रोटोटाइप पर हमारा नामनाम कार्य है, तो वास्तव में व्यक्ति का एक उदाहरण बनाएं और फिर नामनाम फ़ंक्शन को कॉल करें।

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

तो सभी एक साथ एक व्यक्ति निर्माणकर्ता बनाने के लिए कोड, एक फ़ंक्शन को इसे प्रोटोटाइप में जोड़कर, एक व्यक्तिगत उदाहरण बना रहा है, और फिर फ़ंक्शन को इसके प्रोटोटाइप पर कॉल करना इस तरह दिखता है।

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'

अब देखते हैं कि जब आप जावास्क्रिप्ट में 'नए' कीवर्ड का उपयोग करते हैं तो वास्तव में क्या हो रहा है। पहली बात जो आपको ध्यान देनी चाहिए वह यह है कि हमारे उदाहरण में 'नया' का उपयोग करने के बाद, हम 'टायलर' पर एक विधि (SayName) को कॉल करने में सक्षम हैं जैसे कि यह एक वस्तु थी - ऐसा इसलिए है क्योंकि यह है। तो सबसे पहले, हम जानते हैं कि हमारा व्यक्ति निर्माता एक ऑब्जेक्ट लौटा रहा है, चाहे हम कोड में देख सकते हैं या नहीं। दूसरा, हम जानते हैं कि क्योंकि हमारा फ़ंक्शन नाम प्रोटोटाइप पर स्थित है, न कि सीधे व्यक्ति के उदाहरण पर, वह वस्तु जो व्यक्ति फ़ंक्शन वापस कर रहा है, उसे विफल लुकअप पर अपने प्रोटोटाइप में प्रतिनिधि होना चाहिए। अधिक सरल शब्दों में, जब हम tyler.sayName कहते हैं () दुभाषिया कहता है, "ठीक है, मैं 'tyler' ऑब्जेक्ट को देखने जा रहा हूं जिसे हमने अभी बनाया है, SayName फ़ंक्शन का पता लगाएं, फिर कॉल करें। एक मिनट रुकिए, मैं इसे यहाँ नहीं देखता - मैं देख रहा हूँ कि मेरा नाम और उम्र है, मुझे प्रोटोटाइप की जाँच करने दें। हाँ, ऐसा लगता है कि यह प्रोटोटाइप पर है, मुझे इसे कॉल करने दें। ”

नीचे इस बात के लिए कोड है कि आप कैसे सोच सकते हैं कि 'नया' कीवर्ड वास्तव में जावास्क्रिप्ट में क्या कर रहा है। यह मूल रूप से उपरोक्त पैराग्राफ का एक कोड उदाहरण है। मैंने 'इंटरप्रेटर व्यू' डाला है या जिस तरह से इंटरप्रेटर ने नोटों के अंदर कोड देखा है।

var Person = function(name, age){
  //The line below this creates an obj object 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;
}

अब 'नया' कीवर्ड वास्तव में जावास्क्रिप्ट में क्या करता है, इसका ज्ञान होने से, कोणीय में एक सेवा तैयार करना आसान हो जाना चाहिए।

सेवा बनाते समय समझने वाली सबसे बड़ी बात यह है कि सेवाओं को 'नए' कीवर्ड के साथ त्वरित किया जाता है। उस ज्ञान को ऊपर दिए गए हमारे उदाहरणों के साथ जोड़ते हुए, अब आपको यह पहचानना चाहिए कि आप अपने गुणों और विधियों को सीधे 'इस' से जोड़ देंगे, जिसे बाद में सेवा से वापस कर दिया जाएगा। आइए इस पर एक नज़र डालें।

मूल रूप से हमने फ़ैक्टरी उदाहरण के साथ जो किया था, उसके विपरीत, हमें एक ऑब्जेक्ट बनाने की ज़रूरत नहीं है, फिर उस ऑब्जेक्ट को वापस लौटाएं, क्योंकि पहले कई बार उल्लेख किया गया था, हमने 'नए' कीवर्ड का उपयोग किया था, इसलिए दुभाषिया उस ऑब्जेक्ट का निर्माण करेगा, क्या इसे प्रतिनिधि के पास भेजना है यह प्रोटोटाइप है, तो काम किए बिना हमारे लिए इसे वापस कर दें।

पहले चीजें पहले, चलो हमारे 'निजी' और सहायक समारोह बनाएँ। यह बहुत परिचित लगना चाहिए क्योंकि हमने अपने कारखाने के साथ सटीक काम किया है। मैं यह नहीं बताऊंगा कि प्रत्येक पंक्ति यहाँ क्या करती है क्योंकि मैंने कारखाने के उदाहरण में, यदि आप भ्रमित हैं, तो कारखाने के उदाहरण को फिर से पढ़ें।

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

});

अब हमारे कारखाने की तरह, सेटआर्टिस्ट, गेटआर्टिस्ट, और कॉल इट्यून्स उपलब्ध होंगे जो भी नियंत्रक हम 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);
      })
  }
});

जैसा कि मैंने पहले उल्लेख किया है, एक बार जब आप वास्तव में समझते हैं कि mentioned नया ’क्या करता है, तो सेवाएं लगभग कोणीय में कारखानों के समान हैं।


12
आप अपने ब्लॉग पर सीधे एक लिंक प्रदान करना चाह सकते हैं। tylermcginnis.com/angularjs-factory-vs-service-vs-provider मैंने पाया कि पढ़ना थोड़ा आसान है।
टायलर कोलियर

3
यहां आपके ब्लॉग को दोहराने के साथ नथिन गलत है, लेकिन मैं मानता हूं कि यह एक ग्रेटा ब्लॉग पोस्ट है।
आर क्लवेन

5
हर एक हुड के तहत क्या करता है, इसका अच्छा विवरण, लेकिन फिर भी यह स्पष्ट नहीं है कि कोई किसी कारखाने पर सेवा का उपयोग क्यों और कब करेगा। दूसरे शब्दों में, जब मैं एक कारखाने द्वारा लौटाए गए नए ऑब्जेक्ट को पसंद करूंगा। मुझे लगता है कि यह सबसे बड़ा भ्रम है।
निंदा

2
मूल रूप से, यदि आप किसी दूरस्थ सेवा के लिए एक स्थायी कनेक्शन बनाना चाहते हैं, जैसे कि एक स्थिर कनेक्शन (कनेक्शन स्थिति, कॉल इतिहास, डेटा भंडारण) के साथ उदाहरण में उल्लिखित आईट्यून्स एपीआई, आप फैक्टरी के साथ जा सकते हैं। यदि आप इसे एक सेवा के रूप में कार्यान्वित करते हैं, तो हर बार जब आप एपीआई से कुछ चाहते हैं तो आप कनेक्शन दोबारा बना लेंगे और वास्तव में इसमें कुछ भी संग्रहीत नहीं कर सकते हैं। क्योंकि हर बार जब आप सेवा को फिर से बनाते हैं, तो आपको एक खाली / डिफ़ॉल्ट ऑब्जेक्ट मिलेगा।
मेकी

4
मुझे नहीं लगता कि यह सही है, @Aznim। जैसा कि अन्य लोगों ने कहा है, दोनों एकल प्रदान करते हैं।
क्रिप्टोवायरस

35

नाम में सुराग है

सेवाएं और कारखाने एक दूसरे के समान हैं। दोनों एक सिंगलटन ऑब्जेक्ट का उत्पादन करेंगे, जिसे अन्य वस्तुओं में इंजेक्ट किया जा सकता है, और इसलिए अक्सर परस्पर विनिमय किया जाता है।

उनका उद्देश्य विभिन्न डिज़ाइन पैटर्न को लागू करने के लिए शब्दार्थ रूप से उपयोग किया जाना है।

सेवा पैटर्न लागू करने के लिए सेवाएँ हैं

एक सेवा पैटर्न वह है जिसमें आपके एप्लिकेशन को कार्यक्षम रूप से संगत इकाइयों में तोड़ा जाता है। एक उदाहरण API एक्सेसर, या व्यावसायिक तर्क का एक सेट हो सकता है।

यह कोणीय में विशेष रूप से महत्वपूर्ण है क्योंकि कोणीय मॉडल आमतौर पर केवल JSON ऑब्जेक्ट्स को एक सर्वर से खींचा जाता है, और इसलिए हमें अपना व्यावसायिक तर्क रखने के लिए कहीं न कहीं आवश्यकता होती है।

यहाँ उदाहरण के लिए एक Github सेवा है। यह गितुब से बात करना जानता है। यह यूआरएल और तरीकों के बारे में जानता है। हम इसे एक नियंत्रक में इंजेक्ट कर सकते हैं, और यह एक वादा वापस करेगा और उत्पन्न करेगा।

(function() {
  var base = "https://api.github.com";

  angular.module('github', [])
    .service('githubService', function( $http ) {
      this.getEvents: function() {
        var url = [
          base,
          '/events',
          '?callback=JSON_CALLBACK'
        ].join('');
        return $http.jsonp(url);
      }
    });
  )();

फैक्ट्रीज़ एक फैक्ट्री पैटर्न को लागू करती हैं

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

angular.module('user', [])
  .factory('User', function($resource) {
    var url = 'http://simple-api.herokuapp.com/api/v1/authors/:id'
    return $resource(url);
  })

हम इसका उपयोग इस तरह करेंगे:

angular.module('app', ['user'])
  .controller('authorController', function($scope, User) {
    $scope.user = new User();
  })

ध्यान दें कि फैक्ट्रियां भी सिंगलटन लौटाती हैं।

फैक्टरियां एक कंस्ट्रक्टर को वापस कर सकती हैं

क्योंकि एक फैक्ट्री बस एक वस्तु लौटाता है, यह किसी भी प्रकार की वस्तु को वापस कर सकता है, जैसे कि आप एक निर्माता फ़ंक्शन को शामिल करते हैं, जैसा कि हम ऊपर देखते हैं।

वस्तुएं एक वस्तु लौटाती हैं; सेवाएं नई हैं

एक और तकनीकी अंतर है जिस तरह से सेवाओं और कारखानों से बना है। ऑब्जेक्ट को जेनरेट करने के लिए एक सर्विस फंक्शन नया होगा। एक फैक्ट्री फ़ंक्शन को बुलाया जाएगा और ऑब्जेक्ट वापस करेगा।

  • सेवाएँ नए निर्माणकर्ता हैं।
  • कारखानों को बस कहा जाता है और एक वस्तु लौटाते हैं।

इसका मतलब है कि एक सेवा में, हम "इस" के लिए अपील करते हैं, जो एक निर्माणकर्ता के संदर्भ में, निर्माण के तहत वस्तु को इंगित करेगा।

इसका वर्णन करने के लिए, यहां एक सेवा और कारखाने का उपयोग करके बनाई गई समान सरल वस्तु है:

angular.module('app', [])
  .service('helloService', function() {
    this.sayHello = function() {
      return "Hello!";
    }
  })
  .factory('helloFactory', function() {
    return {
      sayHello: function() {
        return "Hello!";
      }
    }
  });

2
महान व्याख्या, धन्यवाद! फैक्ट्रियों के नमूना कोड में भी एक प्रकार है जहां Authorइंजेक्टर पैरामीटर होना चाहिए Person
मिखाइल-टी

धन्यवाद @ मिक-टी, मैंने टाइपो तय किया।
सुपरलुमिनरी

1
सेवा पैटर्न का आपका उपयोग गलत है - यह एक कारखाना होना चाहिए। यदि आप .service () के बजाय .factory () कहते हैं, तो आप देखेंगे कि यह ठीक उसी तरह काम करता है। सेवा पैटर्न का अर्थ एक निर्माणकर्ता फ़ंक्शन के साथ आपूर्ति करना है, न कि एक फ़ंक्शन जो एक नई वस्तु लौटाता है। कोणीय (प्रभावी रूप से) आपके निर्माता फ़ंक्शन पर "नया" कहता है। आपकी सेवा के काम करने का एकमात्र कारण यह है कि यदि आप किसी ऑब्जेक्ट को लौटाने वाले एक निर्माता फ़ंक्शन पर "नया" कहते हैं, तो आप वास्तव में निर्मित वस्तु के बजाय वापस लौटी हुई वस्तु प्राप्त करते हैं। और कारखानों का उपयोग आप जो कुछ भी चाहते हैं, केवल मॉडल बनाने के लिए किया जा सकता है।
दान राजा

27

यहाँ सभी उत्तर सेवा और कारखाने के आसपास प्रतीत होते हैं, और यह तब से मान्य है जब से इसके बारे में पूछा जा रहा था। लेकिन यह ध्यान में रखना वहाँ सहित कई अन्य लोगों के हैं कि महत्वपूर्ण यह भी है provider(), value()औरconstant()

याद रखने की कुंजी यह है कि प्रत्येक एक दूसरे का एक विशेष मामला है। श्रृंखला के प्रत्येक विशेष मामले में आपको कम कोड के साथ एक ही काम करने की अनुमति मिलती है। हर एक में कुछ अतिरिक्त सीमाएँ भी होती हैं।

यह तय करने के लिए कि आपको किस कोड का उपयोग करना है, जो आपको कम कोड में वह करने की अनुमति देता है जो आप चाहते हैं। यहाँ एक चित्र दिखाया गया है कि वे कितने समान हैं:

यहां छवि विवरण दर्ज करें

चरण विराम के पूर्ण चरण के लिए और प्रत्येक का उपयोग करने के त्वरित संदर्भ के लिए आप उस ब्लॉग पोस्ट पर जा सकते हैं जहां मुझे यह चित्र मिला है:

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


3
@jacob शायद ऐसा हो, लेकिन मुझे लगता है कि न केवल जब प्रत्येक का उपयोग करने की समग्र अवधारणा, बल्कि यह कि वे सभी एक ही चीज के अनिवार्य रूप से भिन्न रूप हैं।
लुइस पेरेज़

1
@LuisPerez आपके ब्लॉग का लिंक और अंतर बताने वाला वीडियो वास्तव में बहुत अच्छा है। वीडियो से उन उदाहरणों को समझना आसान है :)
एलिन सियोकान

24

app.factory ('fn', fn) बनाम app.service ('fn', fn)

निर्माण

कारखानों के साथ, कोणीय परिणाम प्राप्त करने के लिए फ़ंक्शन को आमंत्रित करेगा। यह परिणाम है कि कैश और इंजेक्ट किया गया है।

 //factory
 var obj = fn();
 return obj;

सेवाओं के साथ, कोणीय नए को बुलाकर कंस्ट्रक्टर फ़ंक्शन को लागू करेगा । निर्मित फ़ंक्शन कैश और इंजेक्ट किया गया है।

  //service
  var obj = new fn();
  return obj;

कार्यान्वयन

फैक्टरियां आमतौर पर एक वस्तु शाब्दिक लौटाती हैं क्योंकि वापसी मूल्य वह है जो नियंत्रकों, इंजेक्शन ब्लॉक, निर्देश आदि में इंजेक्ट किया जाता है

  app.factory('fn', function(){
         var foo = 0;
         var bar = 0;
         function setFoo(val) {
               foo = val;
         }
         function setBar (val){
               bar = val;
         }
         return {
                setFoo: setFoo,
                serBar: setBar
         }
  });

सेवा कार्य आमतौर पर कुछ भी वापस नहीं करते हैं। इसके बजाय, वे आरंभीकरण करते हैं और कार्यों को उजागर करते हैं। कार्य 'इस' का संदर्भ भी दे सकते हैं क्योंकि इसका निर्माण 'नई' का उपयोग करके किया गया था।

app.service('fn', function () {
         var foo = 0;
         var bar = 0;
         this.setFoo = function (val) {
               foo = val;
         }
         this.setBar = function (val){
               bar = val;
         }
});

निष्कर्ष

जब कारखानों या सेवाओं का उपयोग करने की बात आती है तो वे दोनों बहुत समान हैं। उन्हें एक नियंत्रक, निर्देश, रन ब्लॉक आदि में इंजेक्ट किया जाता है, और क्लाइंट कोड में उसी तरह उपयोग किया जाता है। वे दोनों एकल भी हैं - जिसका अर्थ है कि सभी स्थानों के बीच एक ही उदाहरण साझा किया जाता है जहां सेवा / कारखाने को इंजेक्ट किया जाता है।

तो आपको कौन सा पसंद करना चाहिए? या तो एक - वे इतने समान हैं कि मतभेद तुच्छ हैं। यदि आप एक दूसरे का चयन करते हैं, तो बस जागरूक रहें कि उनका निर्माण कैसे किया जाता है, ताकि आप उन्हें ठीक से लागू कर सकें।


सेवा फ़ंक्शंस "कुछ भी नहीं लौटाते हैं", वे अंतर्निहित वस्तु को वापस करते हैं यदि आप अपना स्वयं का रिटर्न स्टेटमेंट निर्दिष्ट नहीं करते हैं (बाद वाले मामले में आपके द्वारा लौटाए गए ऑब्जेक्ट को कारखाने के समान बनाया और कैश किया जाएगा)।
क्रिप्टोवायरस

मुझे लगता है कि आप इसे गलत बता रहे हैं ... जब मैं कहता हूं कि वापसी करते हैं, तो मेरा मतलब सेवा कार्य कार्यान्वयन से है
पिक्सेलबेट

क्या आप सुनिश्चित हैं कि कारखाना भी एकल शहर है?
१.२ian

5

मैंने कुछ समय बिताने के लिए अंतर जानने की कोशिश की है।

और मुझे लगता है कि फ़ैक्टरी फ़ंक्शन मॉड्यूल पैटर्न का उपयोग करता है और सेवा फ़ंक्शन मानक जावा स्क्रिप्ट कंस्ट्रक्टर पैटर्न का उपयोग करता है।


2

फ़ैक्टरी पैटर्न अधिक लचीला है क्योंकि यह कार्यों और मूल्यों के साथ-साथ वस्तुओं को भी लौटा सकता है।

वहाँ सेवा पैटर्न IMHO में बहुत सारे बिंदु नहीं हैं, क्योंकि यह सब कुछ आप बस एक कारखाने के साथ आसानी से कर सकते हैं। अपवाद हो सकते हैं:

  • यदि आप किसी कारण के लिए अपनी त्वरित सेवा के घोषित प्रकार की परवाह करते हैं - यदि आप सेवा पैटर्न का उपयोग करते हैं, तो आपका निर्माता नई सेवा का प्रकार होगा।
  • यदि आपके पास पहले से ही एक निर्माण कार्य है जो आप कहीं और उपयोग कर रहे हैं जिसे आप एक सेवा के रूप में भी उपयोग करना चाहते हैं (हालांकि यदि आप इसमें कुछ भी इंजेक्ट करना चाहते हैं तो बहुत अधिक उपयोग नहीं करते हैं!)।

तर्क है, एक वाक्यविन्यास बिंदु से एक नई वस्तु बनाने के लिए सेवा पैटर्न थोड़ा अच्छा तरीका है, लेकिन यह भी तत्काल खर्च करने के लिए अधिक महंगा है। दूसरों ने संकेत दिया है कि सेवा बनाने के लिए कोणीय "नया" का उपयोग करता है, लेकिन यह बिल्कुल सच नहीं है - यह ऐसा करने में सक्षम नहीं है क्योंकि प्रत्येक सेवा निर्माता के पास अलग-अलग संख्या में पैरामीटर हैं। कोणीय वास्तव में क्या करता है कारखाने के पैटर्न का उपयोग आंतरिक रूप से आपके निर्माता फ़ंक्शन को लपेटने के लिए करता है। फिर यह जावास्क्रिप्ट के "नए" ऑपरेटर को अनुकरण करने के लिए कुछ चालाक गुड़ की पकौड़ी करता है , अपने निर्माता को इंजेक्शन के तर्कों के एक चर संख्या के साथ आमंत्रित करता है - लेकिन आप इस चरण को छोड़ सकते हैं यदि आप सीधे कारखाने के पैटर्न का उपयोग करते हैं, तो इस तरह से आपकी क्षमता में थोड़ी वृद्धि होती है कोड।


फैक्ट्रियों की तुलना में निर्माण के लिए सेवाएं अधिक कुशल हैं क्योंकि कारखाने अपेक्षाकृत महंगी क्लोजर का उपयोग करते हैं और सेवाएं (कक्षाएं) प्रोटोटाइप का लाभ उठा सकती हैं।
जेकोब

@jacob आप बंद होने के बारे में क्या मतलब है यकीन नहीं है? फैक्ट्री केवल एक फ़ंक्शन है जो किसी ऑब्जेक्ट को लौटाता है। आपको केवल एक क्लोजर का उपयोग करना होगा यदि आपकी लौटी हुई वस्तु को "निजी" स्थिति की आवश्यकता होती है। यदि आप एक कंस्ट्रक्टर (सेवा) का उपयोग करते हैं तो भी आपको वही काम करना होगा। मैं हालांकि प्रोटोटाइप के बारे में आपकी बात लेता हूं - हालांकि आप अभी भी एक कारखाने में ऐसा कर सकते थे यदि आप चाहते थे।
दान राजा

function MyFactory(dep1) { var $$foo = 'bar', factory = {}; Object.defineProperties(factory.prototype, { foo: { value: $$foo } }); return factory; } function MyService(dep1) { var $$foo = 'bar'; Object.defineProperties(MyService.prototype, { foo: { value: $$foo } }); } जबकि MyFactory और MyService दोनों प्रोटोटाइप का उपयोग करते हैं, MyFactory अभी भी उस वस्तु के निर्माण के लिए एक हिट हिट लेता है जिसे वापस लौटाया जा रहा है। दोनों उदाहरणों में, उनके पास निजीकरण है, लेकिन MyService में अपेक्षाकृत कोई प्रदर्शन अंतर नहीं है।
जाकोब

1
मेरे लिए, अंतर यह है कि क्या मैं बिना किसी विधि के सीधे कारखाने का उपयोग करना चाहता हूं: MyFactory(someArgument)(पूर्व $http())। यही कारण है कि एक सेवा आप निर्माता को संदर्भित होगी के रूप में साथ संभव नहीं है: MyService(someArgument)
जाकोब ०

ऑब्जेक्ट निर्माण समय पर, मैं वास्तव में यह नहीं देखता कि फैक्ट्री = {} एक प्रदर्शन हिट है, जब आपके कंस्ट्रक्टर को कॉल करता है, तो आपके लिए "यह" जावास्क्रिप्ट इनिशियलाइज़िंग से अधिक है? और मुझे लगता है कि बड़ा प्रदर्शन हिट कोणीय पक्ष पर होता है जब यह आपके निर्माता को एक कारखाने में लपेटता है और फिर "नया" अनुकरण करने के लिए हुप्स के माध्यम से कूदना पड़ता है ताकि यह आपकी निर्भरता को इंजेक्ट कर सके।
दान राजा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.