在AngularJS覆盖的依赖性在运行时 [英] Overriding dependency at runtime in 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屋!