3

確かに、インジェクターに関するいくつかの基本的な点が欠けていますが、なぜこれが正確なのか理解できません

angular.module('app').config(function ($provide) {
    ...
});

この

angular.module('app').config(function ($injector) {
    $injector.invoke(function ($provide) { ... });
});

意図したとおりに動作しますが、これは

app.run(function($provide) {
    ...
});

投げます

エラー: [$injector:unpr] 不明なプロバイダー: $provideProvider <- $provide

上記からわかるように、configプロバイダーとは特別な関係がありますが、runインスタンスを扱っていますが、configブロックをそれほど特別なものにしている理由についてはわかりません。

その結果、$provide外部configブロックにアクセスする方法はありませんangular.injector()か (プロバイダー インスタンスも取得するようですが)。

この質問には、単なる好奇心に加えて、いくつかの実際的な考慮事項もあります。1.4 ではすべての$provide関数がモジュールに公開されていますが、1.3 ではそうではありません。

4

2 に答える 2

5

関数の目的は、サービス、ディレクティブ、コントローラーなどを含むアプリケーション全体に影響を与えるグローバルconfig()構成を実行できるようにすることです。そのため、ブロックは何よりも先に実行する必要があります。ただし、前述の構成を実行して、アプリの残りの部分で使用できるようにする方法が必要です。その方法は、providersを使用することです。config()

プロバイダーを「特別」にしているのは、プロバイダーに 2 つの初期化部分があり、そのうちの 1 つがconfig()ブロックに直接関連していることです。次のコードを見てください。

app.provider('myService', function() {
    var self = {};    
    this.setSomeGlobalProperty = function(value) {
        self.someGlobalProperty = value;
    };

    this.$get = function(someDependency) {
        this.doSomething = function() {
            console.log(self.someGlobalProperty);
        };
    };    
});

app.config(function(myServiceProvider) {
    myServiceProvider.setSomeGlobalProperty('foobar');
});

app.controller('MyCtrl', function(myService) {
    myService.doSomething();
});

config()プロバイダーを関数に挿入すると、関数以外のものにアクセスできます (技術的には関数にアクセスできますが呼び出しは機能しません)。そうすれば、必要な設定を行うことができます。それが最初の初期化部分です。私たちのサービスは と呼ばれていますが、ここでは接尾辞を使用する必要があることに注意してください。$get$getmyServiceProvider

しかし、同じプロバイダーを他の場所に注入すると、Angular は$get()関数を呼び出し、それが返すものをすべて注入します。それが 2 番目の初期化部分です。この場合、プロバイダは通常のサービスと同じように動作します。

$provideとについて$injectorです。config()それらは「構成サービス」であるため、ブロックの外からアクセスできないことは理にかなっています。できれば、たとえば、別のサービスで使用された後にファクトリを作成できます。

最後に、私はまだ v1.4 で遊んでいないので、なぜその動作が変更されたのかわかりません。誰かが理由を知っている場合は、お知らせください。回答を更新します。

于 2015-04-24T20:43:05.623 に答える
3

いくつかのAngularインジェクターの研究の後、私は自分の質問に徹底的な答えを出すことができました.

基本的に$injector configブロックとproviderコンストラクター関数、および$injector 他のすべての場所には、同じ名前の 2 つの異なるサービスがあり、これらは内部プロバイダー/インスタンス キャッシュで明示的に$provide定義されています (これはプロバイダー キャッシュで定義されているため、のみに注入できますconfig) 。 .

競合状態が発生する可能性があるため、一般的には推奨されませんが、内部サービスをインスタンス キャッシュに公開し、構成固有$provideにして、構成$injectorフェーズの終了後に挿入できるようにすることは可能です。

app.config(function ($provide, $injector) {
  $provide.value('$providerInjector', $injector);
  $provide.value('$provide', $provide);
});

可能なアプリケーションはいつでもサービスプロバイダーを構成しています (可能な場合)

app.run(function ($providerInjector) {
  var $compileProvider = $providerInjector.get('$compileProvider');
  ...
});

実行時に新しいコンポーネントを定義する

app.run(function ($provide) {
  $provide.controller(...);
  ...
});
于 2015-11-14T02:31:29.437 に答える