可以在角$喷油器$ provide.decorator装饰? [英] Can the Angular $injector be decorated with $provide.decorator?
问题描述
的也许这是一个可怕的想法,但如果是,那么请告诉我为什么,然后pretend,它是一个学术活动,将看不到一天生产的光。的
我想一些逻辑添加到角$喷油器服务,当某些服务被注入到其他服务进行监控。因为它似乎角提供装饰服务的机制,我认为这将是一段路要走。但是,下面的code抛出一个错误。
(函数(){
使用严格的; VAR应用= angular.module(应用); 的app.config(['$提供'功能($提供){
$ provide.decorator('$喷油器',['$日志,$代表',addLoggingToInjector]);
}]); 功能addLoggingToInjector($日志,$代表){
VAR baseInstantiate = $ delegate.instantiate;
VAR baseInvoke = $ delegate.invoke; $ delegate.instantiate =功能(类型,当地人){
// $ log.debug('调用$ injector.instantiate'); baseInstantiate(类型,当地人);
}; $ delegate.invoke =功能(FN,自我,当地人){
// $ log.debug('调用$ injector.invoke'); baseInvoke(FN,自我,本地人);
}; 返回$代表;
};
})();
特定的错误是:
未捕获的错误:[$喷油器:modulerr]无法实例模块应用
因:错误:[$喷油器:unpr]未知提供商:$ injectorProvider
块引用>解决方案您不能在$注射器使用角装饰服务。由于阿图尔指出
$注射器
和其他的服务有点不同。但是我们可以创建自己的装饰。为什么我们不能用角的装饰
在code水平的问题是,
$注射器
不具有构造功能 - 有没有$ injectorProvider
。例如这两个返回true:
$ injector.has('$位置');
$ injector.has('$ locationProvider')不过,虽然这将返回true:
$ injector.has('$喷油器')
这将返回false:
$ injector.has('$ injectorProvider')
我们看到的重要性,当我们看<一个href=\"https://github.com/angular/angular.js/blob/a0ed3713899f0ec5f3e1b76ef48fc3acedabe1a5/src/auto/injector.js\">Angular装饰功能:
函数装饰(服务名,decorFn){
VAR origProvider = providerInjector.get(服务名+ providerSuffix)
。原稿$ GET = $ origProvider搞定; origProvider。$ GET =功能(){
VAR origInstance = instanceInjector.invoke(原稿$ GET,origProvider);
返回instanceInjector.invoke(decorFn,空,{$代表:origInstance});
};
}和
providerSuffix ='供应商'
所以角装饰希望在该服务的构造函数运行(
服务名+ providerSuffix
)。务实,,因为我们没有一个$ injectorProvider
我们不能用装饰解决方案
什么我们能做的就是覆盖角度喷油器的
GET
功能通过一个调用原来,角定义的其次,GET
更换喷油器的默认GET
自己我们的函数。我们会将此到
$注射器
,而不是不存在的$ injectorProvider
像这样:的app.config(['$提供,$喷油器'功能(提供$,$喷油器){ //这个函数,我们将添加到喷油器
myFunc的函数=(){
的console.log(注入被称为,参数);
}; //获取喷油器的get函数的副本
VAR origProvider = $喷油器,
origGet = origProvider.get; //覆盖喷油器与我们自己的GET
origProvider.get =功能(){ //调用原始get函数
VAR的returnValue = origGet.apply(这一点,参数); //调用我们的函数
myFunc.apply(这一点,参数); 返回的returnValue;
}
}]);您将看到被注入的提供者是第一次扩充,所以
app.value('安勤','东西');
产生以下日志语句:注射器名为[aValueProvider]
Perhaps this is a terrible idea, but if it is then please tell me why and then pretend that it's an academic exercise that won't see the light of day in production.
I'd like to add some logic to the Angular $injector service, to monitor when certain services are injected into other services. Since it seems that Angular provides a mechanism for decorating services, I thought this would be the way to go. However, the following code throws an error.
(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, self, locals); }; return $delegate; }; })();
The specific error is:
Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to: Error: [$injector:unpr] Unknown provider: $injectorProvider
解决方案You can't use the Angular decorator service on $injector. As Artur notes
$injector
is a bit different from other services. But we can create our own decorator.Why we can't use Angular's decorator
At the code level the issue is that
$injector
doesn't have a constructor function- there's no$injectorProvider
.For example both of these return true:
$injector.has('$location'); $injector.has('$locationProvider')
However, while this returns true:
$injector.has('$injector')
this returns false:
$injector.has('$injectorProvider')
We see the importance when we look at the Angular decorator function:
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}); }; }
And
providerSuffix = 'Provider'
So the Angular decorator expects to operate on the service's constructor (
serviceName + providerSuffix
). Pragmatically, since we don't have an$injectorProvider
we can't use decorator.Solution
What we can do is override the Angular injector's
get
function ourselves by replacing the injector's defaultget
with one that calls the original, Angular defined,get
followed by our function.We'll apply this to
$injector
rather than the nonexistent$injectorProvider
like so: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; } }]);
You'll see the provider being injected is the first augment, so
app.value('aValue', 'something');
yields the following log statement:injector called ["aValueProvider"]
这篇关于可以在角$喷油器$ provide.decorator装饰?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!