可以在角$喷油器$ provide.decorator装饰? [英] Can the Angular $injector be decorated with $provide.decorator?

查看:177
本文介绍了可以在角$喷油器$ 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 default get 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"]

Demo fiddle

这篇关于可以在角$喷油器$ provide.decorator装饰?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆