在AngularJS覆盖的依赖性在运行时 [英] Overriding dependency at runtime in AngularJS

查看:149
本文介绍了在AngularJS覆盖的依赖性在运行时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 $ doggedHttp 服务,这暴露了相同的接口 $ HTTP
现在,我想创建一个 $ doggedResource 服务,这是角 $资源 $ doggedHttp 而不是 $ HTTP 。换句话说我要注入 $ doggedHttp $ HTTP 服务。

此外,在我的应用我希望能够创建 $ doggedResource $资源。因此,我不能简单地覆盖 $ HTTP $ doggedHttp

我想依赖注入应该使这种情况容易解决。难道我错了吗?

相反,我已经深入到角源$ C ​​$ C,终于想出了一个非常丑陋的解决方案:

  angular.module('doggedResource',['ngResource','doggedHttp'])
  的.config(函数(){
    变种ngResource = angular.module('ngResource'),
        doggedResource = angular.module('doggedResource');    //下面的替换与ngResource在$资源工厂的占位符
    doggedResource._invokeQueue [1] [2] [1] [2] = ngResource._invokeQueue [0] [2] [1] [2];
})
.factory('$ doggedResource',['$ doggedHttp','$解析,空/ *这只是一个占位符* /]);

有没有更好的解决办法?


备注,我们不能用 $ provide.decorator 来替换注入 $ HTTP 服务。
为了说明问题,这里有href=\"http://$c$c.angularjs.org/1.0.8/angular-resource.js\" rel=\"nofollow\">角resource.js

  angular.module('ngResource',['NG'])。
  工厂('$资源',['$ HTTP,$解析',函数($ HTTP,$解析){    功能ResourceFactory(URL,paramDefaults,动作){
    }    返回ResourceFactory;
  }

综观上述code时, $ provide.decorator 回调将被传递ResourceFactory作为参数。当时的依赖性 $ HTTP 已经得到解决。而且,由于使用ResourceFactory $ HTTP A闭包内,我们不能改变它。

 的.config(函数($提供){
  $ provide.decorator('$资源,[$委托功能($代表){
    //这里$委托是有ResourceFactory
    //已由封闭相连`$ http`。
  }
}


解决方案

您或许应该写的一切是有在 $ doggedHttp 在一个装饰的逻辑 $ HTTP 。一旦你装饰 $ HTTP ,一切都应该正常工作

编辑:校正条​​件

 的.config(函数($提供){
  $ provide.decorator('$ HTTP,[$委托功能($代表){
    //这里$代表是$ HTTP的功能。
    功能$ doggedHttp(配置){
        //这里写你的存储逻辑。        //路线所有的$ HTTP到$代表在结束通话...
        返回$委托(配置);
    }
    //不要忘记创建快捷方式方法覆盖。
    // createShortMethods('弄','删除','头','JSONP');
    // createShortMethodsWithData('后','放');    //这是你希望做什么简单的解决方案..
    如果(条件){
         返回$ doggedHttp;
    }
    其他{
         返回$代表;
    }    //最后返回$ doggedHttp(而不是$代表)  }
}

另外,你可以写在请求拦截所有存储的逻辑 - 您可以在里面注入予取予求一样,所以储存您的来电,并重新申请即可也可以在该阶段进行。

I have a service called $doggedHttp, which exposes the same interface as $http. Now I want to create a $doggedResource service which is the angular $resource service on top of $doggedHttp instead of $http. In other word I want to inject $doggedHttp as the $http service.

Also, in my application I want to be able to create both $doggedResource and $resource. Thus I cannot simply override $http with $doggedHttp.

I thought dependency injection should make this scenario easy to solve. Am I wrong ?

Instead I had to go deep into the angular source code to finally came up with a quite ugly solution :

angular.module('doggedResource', ['ngResource', 'doggedHttp'])
  .config(function() {
    var ngResource = angular.module('ngResource'),
        doggedResource = angular.module('doggedResource');

    // replace the placeholder below with the $resource factory from ngResource
    doggedResource._invokeQueue[1][2][1][2] = ngResource._invokeQueue[0][2][1][2];
})
.factory('$doggedResource', ['$doggedHttp', '$parse', null /* this is just a placeholder */]);

Is there a better solution ?


Remark that we cannot use $provide.decorator to replace the injected $http service. To illustrate the problem, here are the relevant parts of angular-resource.js :

angular.module('ngResource', ['ng']).
  factory('$resource', ['$http', '$parse', function($http, $parse) {

    function ResourceFactory(url, paramDefaults, actions) {
    }

    return ResourceFactory;
  }

Looking at the code above, the $provide.decorator callback will be passed ResourceFactory as an argument. At that time the dependency $http has already been resolved. And since ResourceFactory use $http inside a closure we cannot change it.

.config(function($provide) {
  $provide.decorator( '$resource', [ "$delegate", function( $delegate ) {
    // here $delegate is the ResourceFactory which has 
    // already been linked to `$http` by a closure.
  }
}

解决方案

You should probably write all the logic that is there in $doggedHttp in a decorator for $http. Once you decorate $http, everything should work fine

EDIT : Correction for condition.

.config(function($provide) {
  $provide.decorator( '$http', [ "$delegate", function( $delegate ) {
    // here $delegate is the $http function.
    function $doggedHttp(config){
        //write your storage logic here.

        // route all the $http calls through $delegate at the end... 
        return $delegate(config);
    }
    //dont forget to create shortcut method overrides.
    //createShortMethods('get', 'delete', 'head', 'jsonp');
    //createShortMethodsWithData('post', 'put');

    // This is the simplest solution to what you wish to do..
    if( condition ) {
         return $doggedHttp; 
    }
    else { 
         return $delegate;
    }     

    //finally return the $doggedHttp ( and not the $delegate ) 

  }
}

Alternately, you can write all your storage logic in a request interceptor - You can inject anything and everything in there as well, so storing your calls and re-requesting can also be done at that stage.

这篇关于在AngularJS覆盖的依赖性在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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