2015-04-28 26 views
6

Hôm nay tôi thấy rằng $injector được tiêm vào cấu hình hoặc nhà cung cấp khác với $injector được tiêm vào dịch vụ, nhà máy hoặc bộ điều khiển.

get() chức năng từ $ kim phun này hoạt động khác nhau.

$injector từ cấu hình hoặc nhà cung cấp, không thể get() bất kỳ dịch vụ nào! $injector.get('myService') ném Error: [$injector:unpr] Unknown provider: myService, nhưng $injector.has('myService') trả về giá trị đúng. Điều đó rất lạ.

$injector từ dịch vụ hoặc bộ điều khiển hoạt động bình thường.

Đây là một mẫu mã cho sự hiểu biết tốt hơn:

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

Ai có thể giải thích tại sao có hai kim phun khác nhau?

Và làm cách nào tôi có thể sử dụng $ injector từ nhà cung cấp/cấu hình để dịch vụ tiêm (sau khi dịch vụ đã được khởi tạo, tất nhiên)?

P.S. Tôi sử dụng góc nghiêng 1.3.13

+0

Câu hỏi của bạn có một chút không rõ ràng. Bạn muốn đạt được gì trong nhà cung cấp/cấu hình? Bạn có thể cung cấp cho một trường hợp sử dụng? –

+0

Trường hợp sử dụng? Ví dụ: nhận dịch vụ thông qua $ injector trong phần cấu hình. Hoặc nhà cung cấp. Sau khi khởi tạo dịch vụ, tất nhiên. Trong trường hợp của tôi (nó rất phức tạp để hiển thị) tôi thêm callbacks cho nhà cung cấp trong phần cấu hình. Và trong gọi lại, tôi muốn sử dụng dịch vụ của mình. DI không thể giúp tôi với điều đó, vì vậy tôi sử dụng $ injector. Gọi lại này sẽ được gọi từ bộ điều khiển, khi dịch vụ đã được khởi tạo. –

Trả lời

8

tôi thấy vấn đề này trên github: https://github.com/angular/angular.js/issues/5559

Trong chức năng cấu hình, $ injector là cung cấp injector, nơi mà trong chức năng chạy, $ injector là dụ phun.

Một trong những $ injector ở giai đoạn cấu hình (chỉ các nhà cung cấp và hằng số có thể truy cập), và một trong những $ injector ở giai đoạn chạy.Sự nhầm lẫn có thể là bạn đang nghĩ rằng $ injector sửa đổi chính nó để bao gồm các công cụ mới khi nó đi qua dòng từ cấu hình để chạy, nhưng đó không phải là sự thật. Chúng là hai đối tượng riêng biệt (mặc dù có liên quan), với các cache riêng của chúng.

Một lý do sâu sắc hơn cho sự phân đôi này có thể đến từ việc học sâu về $ injector internals, nhưng có vẻ như nó là DRY-ed khá hardcore, và hai loại kim tiêm chia sẻ gần như tất cả các hành vi tương tự , ngoại trừ cách chúng đối phó với "cache cache" trong cache của chúng.

Chúng tôi sẽ đại tu vòi phun trong v2, do đó, điều này sẽ được sửa chữa ở đó (loại bỏ pha cấu hình là một trong các mục tiêu của vòi phun v2).

Có vẻ như thực sự có hai kim phun khác nhau và nhà phát triển góc sẽ không khắc phục hành vi đó (trong các phiên bản < 2.0). Và không ai thêm một lưu ý về khía cạnh đó vào tài liệu $ injector vì lý do nào đó.

Tôi không thể tìm thấy cách thực sự nhận được thể hiện bộ phận bên trong khối cấu hình không có thủ thuật hacky. Vì vậy, tôi viết một nhà cung cấp dễ thương để giải quyết loại vấn đề đó.

.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

kiểm tra điều này: [các kim phun kép] (http://taoofcode.net/studying-the-angular-injector-the-twin-injectors/) – alexyangfox

1

Ok. Sau khi đọc ý kiến ​​của bạn, đây là câu trả lời của tôi.

tôi sửa mã trong liệng để làm cho nó hoạt động, khi triệu gọi providerInjector.get() mã nên được như sau:

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

Theo angular docs sau đây được trích dẫn cho cấu hình và chạy các khối:

  • Khối cấu hình - được thực hiện trong quá trình đăng ký nhà cung cấp và giai đoạn cấu hình. Chỉ các nhà cung cấp và hằng số mới có thể được đưa vào các khối cấu hình. Điều này nhằm ngăn chặn khởi tạo ngẫu nhiên các dịch vụ trước khi chúng hoàn toàn được cấu hình .
  • Chạy các khối - được thực hiện sau khi bộ phun được tạo và được sử dụng để khởi động ứng dụng. Chỉ các cá thể và hằng số có thể được tiêm vào các khối chạy. Điều này nhằm ngăn chặn thêm cấu hình trong thời gian chạy ứng dụng.

Điều này đơn giản nghĩa là bạn không thể nhận các phiên bản dịch vụ bên trong khối cấu hình.

+0

@Harry Burns vui lòng kiểm tra mã đã chỉnh sửa hoạt động trong máy plunker của bạn –

+0

myProvider.providerInjector.get ('myServiceProvider') sẽ chỉ trả về trình bao bọc của nhà cung cấp dịch vụ chứ không phải bản thân dịch vụ. Và bạn không trả lời câu hỏi đầu tiên của tôi - tại sao có hai $ kim phun? Và sự khác biệt là gì? Và làm thế nào để có được "dịch vụ $ injector" trong khối cấu hình? –

+0

sau đó bạn không nghĩ rằng bạn có hai câu hỏi ở đây. 1. Tại sao hai kim phun $ khác nhau. 2. Cách sử dụng $ inject trong config. ? Đối với câu hỏi thứ hai của bạn câu trả lời là, bạn không thể sử dụng $ injector trong config, bởi vì trong các khối cấu hình ta không thể khởi tạo dịch vụ. Như tôi đã đề cập trong câu trả lời ở trên. –

Các vấn đề liên quan