Angular.js में अन्य लोगों को क्या "चीजें" इंजेक्ट की जा सकती हैं?


142

मुझे एंगुलर में डिपेंडेंसी इंजेक्शन समझने में थोड़ी मुश्किल हो रही है। तो मेरा प्रश्न यह है कि क्या कोई भी व्यक्ति "प्रकार" की व्याख्या कर सकता है, जैसे नियंत्रक, कारखाने, प्रदाता, आदि। क्या हम उसी "प्रकार" के अन्य उदाहरणों सहित अन्य में इंजेक्ट कर सकते हैं?

मैं वास्तव में क्या देख रहा हूं यह तालिका y / n से भरी हुई है। समान पंक्ति / स्तंभ वाली कोशिकाओं के लिए, इसका अर्थ है कि एक "प्रकार" के मान को दूसरे में उसी "प्रकार" के साथ इंजेक्ट करना

+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Constant       |          |            |           |         |        |          |         |       |
| Controller     |          |            |           |         |        |          |         |       |
| Directive      |          |            |           |         |        |          |         |       |
| Factory        |          |            |           |         |        |          |         |       |
| Filter         |          |            |           |         |        |          |         |       |
| Provider       |          |            |           |         |        |          |         |       |
| Service        |          |            |           |         |        |          |         |       |
| Value          |          |            |           |         |        |          |         |       |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+

यहाँ प्रतिक्रिया docs.angularjs.org/guide/providers#conclusion
JFouad

जवाबों:


391

इसके बजाय कि "हां" और "नहीं" के साथ तालिका में बिना किसी स्पष्टीकरण के भरें, मैं थोड़ा और अधिक विस्तार में जाऊंगा।

[नोट, परिष्करण के बाद जोड़ा गया: यह समाप्त हो रहा है ... मुझे उम्मीद से थोड़ा अधिक लंबा। वहाँ एक tl है; डॉ। तल पर; लेकिन मुझे आशा है कि यह सूचनात्मक साबित होता है।]

[इस जवाब को AngularJS wiki: Understanding Dependency Injection ] में भी जोड़ा गया है।


प्रदाता ( $provide)

$provideसेवा कोणीय बता कैसे नए इंजेक्शन चीज़ें बनाने के लिए उत्तरदायी है; इन चीजों को सेवा कहा जाता है । सेवा प्रदाताओं द्वारा बताई गई चीजों को परिभाषित किया जाता है , जिसे आप उपयोग करते समय बनाते हैं $provide। एक प्रदाता को परिभाषित करना सेवा providerपर विधि के माध्यम से किया जाता है $provide, और आप $provideकिसी एप्लिकेशन के configफ़ंक्शन में इंजेक्ट होने के लिए कहकर सेवा को पकड़ सकते हैं । एक उदाहरण कुछ इस तरह हो सकता है:

app.config(function($provide) {
  $provide.provider('greeting', function() {
    this.$get = function() {
      return function(name) {
        alert("Hello, " + name);
      };
    };
  });
});

यहां हमने एक नई प्रदाता को सेवा के लिए परिभाषित किया है greeting; हम greetingकिसी भी इंजेक्टेबल फंक्शन (जैसे कि बाद में, उस पर अधिक) में नामित वैरिएबल को इंजेक्ट कर सकते हैं और एंगुलर सेवा के $getएक नए उदाहरण को वापस करने के लिए प्रदाता के फ़ंक्शन को कॉल करेंगे । इस मामले में, जो चीज इंजेक्ट की जाएगी वह एक फ़ंक्शन है जो नाम के आधार पर एक nameपैरामीटर और alertएक संदेश लेता है । हम इसे इस तरह उपयोग कर सकते हैं:

app.controller('MainController', function($scope, greeting) {
  $scope.onClick = function() {
    greeting('Ford Prefect');
  };
});

अब यहाँ चाल है। factory, serviceऔर valueसभी एक प्रदाता के विभिन्न भागों को परिभाषित करने के लिए सिर्फ शॉर्टकट हैं - अर्थात्, वे एक प्रदाता को परिभाषित करने का एक साधन प्रदान करते हैं, जिसमें वह सभी सामग्री टाइप करने के बिना। उदाहरण के लिए, आप ठीक उसी प्रदाता को इस तरह लिख सकते हैं :

app.config(function($provide) {
  $provide.factory('greeting', function() {
    return function(name) {
      alert("Hello, " + name);
    };
  });
});

यह समझना महत्वपूर्ण है, इसलिए मैं पुनः विचार करूंगा: हुड के तहत, AngularJS ठीक उसी कोड को कॉल कर रहा है जो हमने हमारे लिए ऊपर ( $provide.providerसंस्करण) लिखा था । शाब्दिक रूप से, दो संस्करणों में 100% कोई अंतर नहीं है। ठीक उसी तरह से काम करता है - अगर हम जो भी अपने फंक्शन (उर्फ हमारे फंक्शन) से लौटते हैं, वह हमेशा ठीक वैसा ही होता है, तो हम कोड यूज करके भी लिख सकते हैं । उदाहरण के लिए, चूंकि हम हमेशा अपनी सेवा के लिए एक ही फ़ंक्शन वापस करते हैं, इसलिए हम इसे परिभाषित करने के लिए भी उपयोग कर सकते हैं :value$getfactoryvaluegreetingvalue

app.config(function($provide) {
  $provide.value('greeting', function(name) {
    alert("Hello, " + name);
  });
});

फिर, यह इस फ़ंक्शन को परिभाषित करने के लिए हमारे द्वारा उपयोग की गई अन्य दो विधियों के समान 100% है - यह केवल कुछ टाइपिंग को बचाने का एक तरीका है।

अब आप शायद इस कष्टप्रद app.config(function($provide) { ... })बात पर गौर कर रहे हैं जिसका मैं उपयोग कर रहा हूं नए प्रदाताओं को परिभाषित करने के बाद ( ऊपर दिए गए किसी भी तरीके के माध्यम से) इतना सामान्य है, एंगुलरजेएस $providerऔर भी टाइपिंग को बचाने के लिए सीधे मॉड्यूल ऑब्जेक्ट पर विधियों को उजागर करता है :

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

myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);

ये सभी वही क्रिया करते हैं जो app.config(...)पहले इस्तेमाल किए गए अधिक वर्बोज़ संस्करणों के रूप में होती हैं ।

अभी तक मैंने जो एक इंजेक्शन छोड़ा है वह है constant। अभी के लिए, यह कहना काफी आसान है कि यह ठीक वैसे ही काम करता है value। हम देखेंगे कि बाद में एक अंतर है।

समीक्षा करने के लिए , ये सभी कोड सटीक समान कार्य कर रहे हैं :

myMod.provider('greeting', function() {
  this.$get = function() {
    return function(name) {
      alert("Hello, " + name);
    };
  };
});

myMod.factory('greeting', function() {
  return function(name) {
    alert("Hello, " + name);
  };
});

myMod.value('greeting', function(name) {
  alert("Hello, " + name);
});

इंजेक्टर ( $injector)

इंजेक्टर वास्तव में हमारे द्वारा प्रदान किए गए कोड का उपयोग करके हमारी सेवाओं के उदाहरण बनाने के लिए ज़िम्मेदार है $provide(कोई सज़ा नहीं)। किसी भी समय आप एक फ़ंक्शन लिखते हैं जो इंजेक्शन को तर्क देता है, आप काम पर इंजेक्टर देख रहे हैं। प्रत्येक AngularJS एप्लिकेशन में एक सिंगल है $injectorजो तब बनता है जब एप्लिकेशन पहली बार शुरू होता है; आप $injectorकिसी भी इंजेक्टेबल फंक्शन में इंजेक्ट करके इसकी पकड़ प्राप्त कर सकते हैं (हाँ, $injectorखुद को इंजेक्ट करना जानते हैं!)

आपके पास एक बार $injector, आप सेवा getके नाम से कॉल करके परिभाषित सेवा का एक उदाहरण प्राप्त कर सकते हैं । उदाहरण के लिए,

var greeting = $injector.get('greeting');
greeting('Ford Prefect');

इंजेक्टर कार्यों में सेवाओं को इंजेक्ट करने के लिए भी जिम्मेदार है; उदाहरण के लिए, आप जादुई तरीके से इंजेक्टर की invokeविधि का उपयोग करके किसी भी फ़ंक्शन में सेवाओं को इंजेक्ट कर सकते हैं ;

var myFunction = function(greeting) {
  greeting('Ford Prefect');
};
$injector.invoke(myFunction);

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

तो, अपने प्रश्न का उत्तर देने के लिए, आप किसी भी फ़ंक्शन$injector.invoke में सेवाओं को इंजेक्ट कर सकते हैं जिसे साथ बुलाया जाता है । यह भी शामिल है

  • नियंत्रक परिभाषा कार्य
  • निर्देश परिभाषा कार्य
  • फ़िल्टर परिभाषा कार्य
  • $getप्रदाताओं के तरीके ( factoryपरिभाषा कार्य उर्फ )

चूँकि constants और values हमेशा एक स्थैतिक मान लौटाते हैं, उन्हें इंजेक्टर के माध्यम से नहीं लगाया जाता है, और इस प्रकार आप उन्हें किसी भी चीज़ से इंजेक्ट नहीं कर सकते हैं।

प्रदाताओं को कॉन्फ़िगर करना

आप सोच रहे होंगे कि कोई भी इस provideपद्धति से पूर्ण-प्रदाता प्रदान करने की जहमत क्यों उठाएगा factory, अगर valueइत्यादि बहुत आसान हैं। इसका उत्तर यह है कि प्रदाता बहुत सारे कॉन्फ़िगरेशन की अनुमति देते हैं। हमने पहले ही उल्लेख किया है कि जब आप प्रदाता के माध्यम से एक सेवा बनाते हैं (या कोई भी शॉर्टकट जो आपको कोणीय देता है), आप एक नया प्रदाता बनाते हैं जो यह बताता है कि उस सेवा का निर्माण कैसे किया जाता है। मैंने क्या उल्लेख नहीं किया है कि इन प्रदाताओं configको आपके आवेदन के अनुभागों में इंजेक्ट किया जा सकता है ताकि आप उनके साथ बातचीत कर सकें!

सबसे पहले, कोणीय दो चरणों में आपका आवेदन चलाता है - configऔर runचरण। configचरण, हमने देखा कि के रूप में, आप आवश्यक के रूप में किसी भी प्रदाताओं सेट कर सकते हैं जहां है। यह वह जगह भी है जहां निर्देशक, नियंत्रक, फिल्टर, और जैसे सेट हो जाते हैं। runचरण, के रूप में आप अनुमान लगा सकता है, जहां कोणीय वास्तव में अपने डोम संकलित करता है तथा अपने अनुप्रयोग शुरू होता है।

आप इन चरणों में myMod.configऔर myMod.runकार्यों के साथ चलाने के लिए अतिरिक्त कोड जोड़ सकते हैं - प्रत्येक उस विशिष्ट चरण के दौरान चलाने के लिए एक फ़ंक्शन लेते हैं। जैसा कि हमने पहले खंड में देखा था, ये फ़ंक्शन इंजेक्टेबल हैं - हमने $provideअपने पहले कोड नमूने में अंतर्निहित सेवा को इंजेक्ट किया । हालांकि, ध्यान देने योग्य बात यह है कि चरण के दौरान config, केवल प्रदाताओं को इंजेक्ट किया जा सकता है ( AUTOमॉड्यूल में सेवाओं के अपवाद के साथ - $provideऔर $injector)।

उदाहरण के लिए, निम्नलिखित की अनुमति नहीं है :

myMod.config(function(greeting) {
  // WON'T WORK -- greeting is an *instance* of a service.
  // Only providers for services can be injected in config blocks.
});

आपके पास जो भी सेवाएँ हैं उनके लिए आपके पास कोई भी प्रदाता है:

myMod.config(function(greetingProvider) {
  // a-ok!
});

एक महत्वपूर्ण अपवाद है: constantएस, चूंकि उन्हें बदला नहीं जा सकता है, उन्हें configब्लॉकों के अंदर इंजेक्ट करने की अनुमति है (यह इस प्रकार है कि वे valueएस से अलग हैं )। वे अकेले अपने नाम से Providerपहुंचते हैं (कोई आवश्यक प्रत्यय नहीं)।

जब भी आपने किसी सेवा के लिए प्रदाता को परिभाषित किया है, तो उस प्रदाता का नाम हो जाता है serviceProvider, जहां serviceसेवा का नाम होता है। अब हम प्रदाताओं की शक्ति का उपयोग कर सकते हैं कुछ और अधिक जटिल सामान करते हैं!

myMod.provider('greeting', function() {
  var text = 'Hello, ';

  this.setText = function(value) {
    text = value;
  };

  this.$get = function() {
    return function(name) {
      alert(text + name);
    };
  };
});

myMod.config(function(greetingProvider) {
  greetingProvider.setText("Howdy there, ");
});

myMod.run(function(greeting) {
  greeting('Ford Prefect');
});

अब हमारे पास हमारे प्रदाता पर एक फ़ंक्शन है जिसे setTextहम अनुकूलित करने के लिए उपयोग कर सकते हैं alert; हम configइस पद्धति को कॉल करने और सेवा को अनुकूलित करने के लिए एक ब्लॉक में इस प्रदाता तक पहुंच प्राप्त कर सकते हैं । जब हम अंत में अपना ऐप चलाते हैं, तो हम इस greetingसेवा को पकड़ सकते हैं , और यह देखने की कोशिश कर सकते हैं कि हमारा अनुकूलन प्रभावी हुआ।

चूँकि यह एक अधिक जटिल उदाहरण है, यहाँ एक कार्य प्रदर्शन है: http://jsfiddle.net/BinaryMuse/9GYYY/

नियंत्रकों ( $controller)

नियंत्रक कार्यों में इंजेक्ट किया जा सकता है, लेकिन नियंत्रकों को खुद को अन्य चीजों में इंजेक्ट नहीं किया जा सकता है। ऐसा इसलिए है क्योंकि प्रदाता के माध्यम से नियंत्रक नहीं बनाए जाते हैं। इसके बजाय, एक अंतर्निहित कोणीय सेवा है जिसे कहा जाता है $controllerकि आपके नियंत्रक स्थापित करने के लिए जिम्मेदार है। जब आप कॉल करते हैं myMod.controller(...), तो आप वास्तव में इस सेवा के प्रदाता तक पहुंच बना रहे हैं , जैसे पिछले अनुभाग में।

उदाहरण के लिए, जब आप एक नियंत्रक को इस तरह परिभाषित करते हैं:

myMod.controller('MainController', function($scope) {
  // ...
});

आप वास्तव में यह क्या कर रहे हैं:

myMod.config(function($controllerProvider) {
  $controllerProvider.register('MainController', function($scope) {
    // ...
  });
});

बाद में, जब कोणीय को आपके नियंत्रक का एक उदाहरण बनाने की आवश्यकता होती है, तो यह $controllerसेवा का उपयोग करता है (जो बदले में $injectorआपके नियंत्रक फ़ंक्शन को लागू करने के लिए उपयोग करता है ताकि इसे इसकी निर्भरताएं भी इंजेक्शन मिलें)।

फिल्टर और निर्देश

filterऔर directiveठीक उसी तरह काम करते हैं जैसे controller; filterएक सेवा $filterऔर उसके प्रदाता का उपयोग करता है $filterProvider, जबकि directiveएक सेवा $compileऔर उसके प्रदाता का उपयोग करता है $compileProvider। कुछ लिंक:

अन्य उदाहरणों के अनुसार, myMod.filterऔर myMod.directiveइन सेवाओं को कॉन्फ़िगर करने के लिए शॉर्टकट हैं।


tl; डॉ

इसलिए, संक्षेप में, किसी भी फ़ंक्शन को जिसे बुलाया जाता $injector.invoke है, में इंजेक्ट किया जा सकता है । इसमें आपके चार्ट से (लेकिन यह सीमित नहीं है) शामिल है:

  • नियंत्रक
  • आदेश
  • फ़ैक्टरी
  • फिल्टर
  • प्रदाता $get(जब एक वस्तु के रूप में प्रदाता को परिभाषित करना)
  • प्रदाता फ़ंक्शन (जब निर्माता फ़ंक्शन को निर्माता फ़ंक्शन के रूप में परिभाषित करता है)
  • सर्विस

प्रदाता नई सेवाएँ बनाता है जिन्हें चीजों में इंजेक्ट किया जा सकता है । यह भी शामिल है:

  • स्थिर
  • फ़ैक्टरी
  • प्रदाता
  • सर्विस
  • मूल्य

उस ने कहा, अंतर्निहित सेवाओं की तरह है $controllerऔर इंजेक्ट किया $filter जा सकता है, और आप उपयोग कर सकते हैं उन फ़िल्टर और नियंत्रकों को उन तरीकों से परिभाषित करने के लिए उन सेवाओं का (भले ही आपके द्वारा परिभाषित की गई चीजें स्वयं द्वारा सक्षम न हों, चीजों में इंजेक्ट किया गया)।

इसके अलावा, किसी भी इंजेक्टर-इनवोक किए गए फ़ंक्शन को किसी भी प्रदाता द्वारा प्रदान की गई सेवा के साथ इंजेक्ट किया जा सकता है - कोई प्रतिबंध नहीं है ( यहां सूचीबद्ध configऔर runमतभेदों के अलावा )।


6
वाह! ऐसे विस्तार से जवाब देने के लिए समय निकालने के लिए धन्यवाद! मैंने इसे दो बार पढ़ा है, और मुझे लगता है कि मैं काफी समझ गया हूं। गोना ने इसका अध्ययन किया और जिन लिंक्स को आपने आज विस्तार से बताया है। और बिल्ली के लिए एक और +1। :)
user1527166

18
सबसे उपयोगी और विस्तृत SO उत्तरों में से एक मैं भर आया हूँ - धन्यवाद!
गोड्स

11
यह उत्तर एक नए स्तर के कमाल को परिभाषित करता है। रोशन सामान।
न्यूर्ज न्या

4
अब तक के सबसे अच्छे संसाधन मैं AngularJS के लिए आया हूं। धन्यवाद।
कोड 90

5
सचमुच मैंने देखा है AngularJS प्रलेखन का सबसे अच्छा टुकड़ा। जाने के लिए रास्ता!
इयान डंकन

13

बाइनरीमुज प्रदाता, कारखानों, और सेवाओं के बारे में अपने अद्भुत जवाब में सभी को एक ही बात बताता है।

नीचे एक छवि है जो मुझे लगता है कि नेत्रहीन उसकी बात को स्पष्ट कर सकते हैं:

AngularJS वे सभी सिर्फ प्रदाता हैं
(स्रोत: Simplygoodcode.com )


7

मिशेल ने शानदार जवाब दिया। मैं केवल यह बताना चाहता हूं कि निर्देशों को इंजेक्ट किया जा सकता है। यदि आपके पास एक निर्देश नाम है myThing, तो आप इसे इसके साथ इंजेक्ट कर सकते हैं myThingDirective: यहां एक आकस्मिक उदाहरण है

उपरोक्त उदाहरण बहुत व्यावहारिक नहीं है, हालांकि निर्देश को इंजेक्ट करने की क्षमता तब उपयोगी होती है जब आप उस निर्देश को सजाना चाहते हैं ।


ऐसा लगता है कि उस निर्देश को सजाने के लिए दूसरा उदाहरण कोणीय 1.4 के बाद से काम नहीं करता है। ( वहाँ जुआन
बिसकिया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.