2013-10-14 3 views
4

У меня есть служба под названием $doggedHttp, которая предоставляет тот же интерфейс, что и $http. Теперь я хочу создать услугу $doggedResource, которая является угловым сервисом $resource на верхней части $doggedHttp вместо $http. Другими словами, я хочу ввести $doggedHttp в качестве услуги $http.Переопределяющая зависимость во время выполнения в AngularJS

Кроме того, в моем приложении я хочу иметь возможность создавать как $doggedResource, так и $resource. Таким образом, я не могу просто переопределить $http с $doggedHttp.

Я думал, что инъекция зависимостей должна облегчить этот сценарий. Я ошибаюсь ?

Вместо этого мне пришлось углубиться в исходный код углового, наконец, придумал довольно уродливый решение:

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 */]); 

Есть ли лучшее решение?


замечание, что мы не можем использовать $provide.decorator заменить впрыскивается $http услугу. Чтобы проиллюстрировать эту проблему, вот соответствующие части angular-resource.js:

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

    function ResourceFactory(url, paramDefaults, actions) { 
    } 

    return ResourceFactory; 
    } 

Глядя на коде выше $provide.decorator обратный вызов будет передан ResourceFactory в качестве аргумента. В то время зависимость $http уже разрешена. И так как ResourceFactory использует $http внутри закрытия, мы не можем его изменить.

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

Итак, ваш «doggedHttp», это собственный модуль? Вы сделали angular.module («doggedHttp», [])? Вы не просто добавили завод в текущий модуль? – frosty

+0

Просто из любопытства, зачем вам это нужно? Если это за издевательство во время модульного тестирования, есть лучшие способы сделать это. – ivarni

+0

@aaronfrost yes 'doggedHttp' - это модуль, который определяет '$ doggedHttp' – recamshak

ответ

0

Вы, вероятно, следует написать всю логику, которая есть в $doggedHttp в декоратора для $http. Как только вы украдете $http, все должно хорошо работать

EDIT: Исправление для состояния.

.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) 

    } 
} 

В качестве альтернативы, вы можете написать всю вашу логику хранения в request interceptor - Вы можете привнести что-нибудь и все там, так что хранение ваших звонков и повторный запрос также можно сделать на данном этапе.

+0

Если я это сделаю, любой вызов службы $ http будет перехвачен. Это не то, что я хочу. Я хочу иметь возможность использовать базовые $ http и $ doggedHttp в одном приложении. – recamshak

+0

Простой, если условие в '$ delegate' не работает для вас? – ganaraj

Смежные вопросы