デコレーター メカニズムは、以前の定義を取得し、その新しいバージョンを返すプロバイダーを作成するための省略表現です。
したがって、次のようにこの機能を模倣できます。
module.provider('$log', function ($logProvider) {
// $logProvider here is the one previously defined, from 'ng'
// unless someone else is overriding too.
this.$get = function ($injector) {
// Invoke the original provider.
var $log = $injector.invoke($logProvider.$get);
var oldInfo = $log.info;
// Override the method.
$log.info = function info() {
oldInfo.apply(this, arguments);
// (not actually useful to alert arguments; just an example)
alert(arguments);
}
return $log;
}
});
もちろん、これによりすべての従属要素のオブジェクトが変更されます。たとえそれらが標準インターフェースに非常に満足していたとしてもです$log
。つまり、どのサービスが標準インターフェースに依存しており、どのサービスが拡張インターフェースに依存しているかをアプリケーションで直接確認する方法がないことを意味します。これは、ラッピングによって既存のメソッドの動作を変更したいだけの場合 (たとえば、ログをサーバーに送信したり、質問で述べたようにトースターを表示したりする場合) に役立ちますが、追加の追加には危険な選択になる可能性があります。標準インターフェイスとの互換性を誤って壊す可能性がある場合、既存の呼び出し元が期待していないメソッド。
代わりに、拡張機能が必要であることがわかっている場所で使用できる新しいサービスを提供し、組み込みの$log
インターフェイスを標準のままにしておく方がよい場合があります。こうすることで、違いを見分けやすくなり、標準の呼び出し元での意図しない動作の変更を回避できます。これは上記と似ていますが、詳細が少し異なります。
module.provider('anotherLog', function ($logProvider) {
this.$get = function ($injector) {
var $log = $injector.invoke($logProvider.$get);
// Create a new object rather than extending the existing one in-place.
// This way the new method is only visible to callers that request
// 'anotherLog' instead of just '$log'.
var anotherLog = angular.extend(Object.create($log), {
sayHello: function sayHello() {
console.log('Hello!');
}
})
return anotherLog;
}
});
これらのアプローチはどちらも、アプリの初期化中に別の「プロバイダー インジェクター」を使用してプロバイダー間の依存関係を処理するという事実を利用しています。$injector
これは、アプリの作成後に使用されるメインとは異なります。プロバイダー インジェクターには、これまでに定義されたすべてのプロバイダーが含まれていますが、結果として得られる などのサービスは含まれません$log
。プロバイダー関数自体はプロバイダー インジェクターで注入されますが、その$get
メソッドは (これらの例に示されているように) main で注入され$injector
ます。
この違いのため、トースターを表示するために他のサービスに依存している場合は$get
、プロバイダー全体ではなく、メソッド自体をそれらのサービスに依存する必要があります。$injector
これにより、プロバイダー インジェクターからのプロバイダーだけでなく、メインのサービスにアクセスできるようになります。