2015-04-28 15 views
6

आज मैंने पाया कि $injector कॉन्फ़िगर या प्रदाता से इंजेक्शन $injector सेवा, कारखाने या नियंत्रक से इंजेक्शन से अलग है।

और get() इस $ इंजेक्टर से कार्य अलग-अलग काम करता है।

$injector कॉन्फ़िगर या प्रदाता से, get() कोई सेवा नहीं दे सकता! $injector.get('myService')Error: [$injector:unpr] Unknown provider: myService फेंकता है, लेकिन $injector.has('myService') सत्य लौटाता है। यह बहुत अजीब है।

$injector सेवा या नियंत्रक से सामान्य रूप से काम करता है।

angular.module('app', []) 

     .provider('myProvider', function ($injector) { 
      this.$get = ['$injector', function (serviceInjector) { 
       return { 
        providerInjector: $injector, 
        serviceInjector: serviceInjector 
       }; 
      }]; 
     }) 

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

     .controller('myCtrl', function ($scope, myProvider) { 
      var providerInjector = myProvider.providerInjector; 
      var serviceInjector = myProvider.serviceInjector; 

      console.log(providerInjector === serviceInjector); // -> false 

      console.log(serviceInjector.has('myService')); // `serviceInjector` has `myService` 
      console.log(getMyService(serviceInjector)); // `serviceInjector` can get `myService` 

      console.log(providerInjector.has('myService')); // `providerInjector` has `myService` too! 
      console.log(getMyService(providerInjector)); // but `providerInjector` can't get `myService`! =(

      function getMyService(injector) { 
       try { 
        injector.get('myService'); 
        return "OK"; 
       } catch (e) { 
        return e.toString(); 
       } 
      } 

     }); 

Here is a plunker to play

किसी को भी व्याख्या कर सकते हैं क्यों दो अलग इंजेक्टर है वहाँ:

यहाँ बेहतर समझ के लिए एक कोड नमूना है?

और मैं सेवा इंजेक्ट करने के लिए प्रदाता/कॉन्फ़िगरेशन से $ इंजेक्टर का उपयोग कैसे कर सकता हूं (सेवा के बाद सेवा शुरू की गई थी)?

पीएस मैं कोणीय 1.3.13

+0

आपका प्रश्न थोड़ा अस्पष्ट है। प्रदाता/कॉन्फ़िगरेशन में आप क्या हासिल करना चाहते हैं? क्या आप एक उपयोग केस दे सकते हैं? –

+0

केस का उपयोग करें? उदाहरण के लिए: कॉन्फ़िगरेशन अनुभाग में $ इंजेक्टर के माध्यम से सेवा प्राप्त करें। या प्रदाता। निश्चित रूप से सेवा शुरू करने के बाद। मेरे मामले में (यह दिखाने के लिए बहुत जटिल है) मैं कॉन्फ़िगरेशन अनुभाग में प्रदाता को कॉलबैक जोड़ता हूं। और कॉलबैक में मैं अपनी सेवा का उपयोग करना चाहता हूं। DI इसके साथ मेरी मदद नहीं कर सकता, इसलिए मैं $ इंजेक्टर का उपयोग करता हूं। इस कॉलबैक को नियंत्रक से बुलाया जाएगा, जब सेवा पहले ही शुरू की गई थी। –

उत्तर

8

मैं GitHub पर इस मुद्दे को मिला: https://github.com/angular/angular.js/issues/5559

config समारोह में, $ इंजेक्टर प्रदाता इंजेक्टर, जहां रन समारोह में, $ इंजेक्टर उदाहरण इंजेक्टर है।

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

इस डिचोटोमी के लिए एक और गहराई से कारण शायद $ इंजेक्टर इंटर्नल की गहरी शिक्षा से आएगा, लेकिन ऐसा लगता है कि यह DRY-ed बहुत कट्टर है, और दो प्रकार के इंजेक्टर लगभग सभी समान व्यवहार साझा करते हैं , इसके अलावा वे अपने उदाहरण कैश में "कैश मिस" से कैसे निपटते हैं।

हम v2 में इंजेक्टर को ओवरहाल करने जा रहे हैं, इसलिए यह वहां ठीक हो जाएगा (कॉन्फ़िगर चरण से छुटकारा पाने इंजेक्टर v2 के उद्देश्यों में से एक है)।

ऐसा लगता है कि वास्तव में दो अलग इंजेक्टर हैं, और कोणीय डेवलपर्स उस व्यवहार को ठीक नहीं करेंगे (संस्करण < 2.0 में)। और किसी ने किसी कारण से $ इंजेक्टर दस्तावेज़ों के लिए उस पहलू के बारे में कोई नोट नहीं जोड़ा।

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

.provider('instanceInjector', function() { 

    var instanceInjector; 

    function get() { 
     return instanceInjector; 
    } 

    function exists() { 
     return !!instanceInjector; 
    } 

    angular.extend(this, { 
     get: get, 
     exists: exists 
    }); 

    this.$get = function ($injector) { 
     instanceInjector = $injector; 

     return { 
      get: get, 
      exists: exists 
     }; 
    } 
}) 

// We need to inject service somewhere. 
// Otherwise $get function will be never executed 
.run(['instanceInjector', function(instanceInjector){}]) 
+1

इसे जांचें: [जुड़वां इंजेक्टर] (http://taoofcode.net/studying-the-angular-injector-the-twin-injectors/) – alexyangfox

1

ठीक है। अपनी टिप्पणियां पढ़ने के बाद, मेरा जवाब यहां है।

मैं इसे काम करने के लिए खनखनाहट में कोड संपादित, जब providerInjector.get() कोड के रूप में किया जाना चाहिए इस प्रकार लागू:

$scope.getMyServiceFromProviderInjector = function() { 
     try { 
       myProvider.providerInjector.get('myServiceProvider');//here is change in provider name 
       return "OK"; 
      } catch (e) { 
       return e.toString(); 
      } 
    }; 

angular docs के अनुसार निम्नलिखित config के लिए उद्धृत किया और चलाया जाता है ब्लॉक:

  • कॉन्फ़िगरेशन ब्लॉक - प्रदाता पंजीकरण और कॉन्फ़िगरेशन चरण के दौरान निष्पादित हो जाएं। केवल प्रदाता और स्थिरांक कॉन्फ़िगरेशन ब्लॉक में इंजेक्शन दिया जा सकता है। सेवाओं की आकस्मिक तत्कालता को कॉन्फ़िगर करने से पहले इसे रोकने के लिए है।
  • रन ब्लॉक - इंजेक्टर के निर्माण के बाद निष्पादित हो जाएं और एप्लिकेशन को किकस्टार्ट करने के लिए उपयोग किया जाता है। रन ब्लॉक में इंजेक्शन किए गए केवल उदाहरण और स्थिरांक हो सकते हैं। यह एप्लिकेशन रन टाइम के दौरान कॉन्फ़िगरेशन को और सिस्टम को रोकने के लिए है।

यह सीधा सा अर्थ है, आप सेवाओं के उदाहरण config ब्लॉक के अंदर नहीं मिल सकता है।

+0

@ हैरी बर्न्स कृपया संपादित कोड को चेक करें जो आपके प्लंकर –

+0

में काम करता है myProvider.providerInjector.get ('myServiceProvider') सेवा के लिए केवल प्रदाता रैपर लौटाएगा, सेवा ही नहीं। और आप मेरे पहले सवाल का जवाब नहीं देते - दो $ इंजेक्टर क्यों हैं? और क्या अंतर है? और कॉन्फ़िगरेशन ब्लॉक में "सेवा $ इंजेक्टर" कैसे प्राप्त करें? –

+0

तो आपको नहीं लगता कि आपके यहां दो प्रश्न हैं। 1. दो अलग-अलग $ इंजेक्टर क्यों। 2. कॉन्फ़िगरेशन में $ इंजेक्ट का उपयोग कैसे करें। ? आपके दूसरे प्रश्न के लिए उत्तर यह है कि, आप कॉन्फ़िगरेशन में $ इंजेक्टर का उपयोग नहीं कर सकते हैं, क्योंकि कॉन्फ़िगरेशन ब्लॉक में कोई भी सेवाओं को तुरंत चालू नहीं कर सकता है। जैसा कि मैंने ऊपर दिए गए उत्तर में उल्लेख किया है। –