也许这是一个可怕的想法,但是如果是,那么请告诉我为什么,然后假装这是一个不会看到生产中的光的学术活动。
我想为Angular $ Injection服务添加一些逻辑,以监控某些服务是否注入其他服务。由于Angular似乎提供了一种装饰服务的机制,所以我认为这是一种方式。但是,以下代码会引发错误。
(function () { 'use strict'; var app = angular.module('app'); app.config(['$provide',function ($provide) { $provide.decorator('$injector',['$log','$delegate',addLoggingToInjector]); }]); function addLoggingToInjector($log,$delegate) { var baseInstantiate = $delegate.instantiate; var baseInvoke = $delegate.invoke; $delegate.instantiate = function (type,locals) { // $log.debug('Calling $injector.instantiate'); baseInstantiate(type,locals); }; $delegate.invoke = function (fn,self,locals) { // $log.debug('Calling $injector.invoke'); baseInvoke(fn,locals); }; return $delegate; }; })();
具体的错误是:
Uncaught Error: [$injector:modulerr] Failed to instantiate module app
due to: Error: [$injector:unpr] Unknown provider: $injectorProvider
您不能在$注射器上使用Angular装饰器服务。由于Artur注释,注射器与其他服务有所不同。但是我们可以创建我们自己的装饰器。
为什么我们不能使用Angular的装饰器
在代码级别的问题是,$ inject没有构造函数 – 没有$ injectProvider。
例如,这两个都返回true:
$injector.has('$location'); $injector.has('$locationProvider')
但是,尽管如此:
$injector.has('$injector')
这会返回false:
$injector.has('$injectorProvider')
当我们看看Angular decorator功能时,我们看到了重要性:
function decorator(serviceName,decorFn) { var origProvider = providerInjector.get(serviceName + providerSuffix),orig$get = origProvider.$get; origProvider.$get = function() { var origInstance = instanceInjector.invoke(orig$get,origProvider); return instanceInjector.invoke(decorFn,null,{$delegate: origInstance}); }; }
和
providerSuffix = 'Provider'
所以Angular装饰器期望在服务的构造函数(serviceName providerSuffix)上运行。实际上,由于我们没有一个$ injectProvider,我们不能使用装饰器。
解
我们可以做的是通过将注射器的默认值替换为调用原始角度的角度定义的角度来取代角度注射器的get
function。
我们将这个应用到$ injector而不是不存在的$ injectProvider像这样:
app.config(['$provide','$injector',function ($provide,$injector) { // The function we'll add to the injector myFunc = function () { console.log("injector called ",arguments); }; // Get a copy of the injector's get function var origProvider = $injector,origGet = origProvider.get; //Override injector's get with our own origProvider.get = function() { // Call the original get function var returnValue = origGet.apply(this,arguments); // Call our function myFunc.apply(this,arguments); return returnValue; } }]);
你会看到被注入的提供者是第一个扩充,所以app.value(‘aValue’,’something’);产生以下日志语句:
injector called ["aValueProvider"]