1

Not an easy one to describe this, but basically I have a service which is set up as a provider so I can configure it. It has an array of APIs used in my project which is initially empty. Various config blocks can add an API object to the array and this seems to be working. I console.log the output each time and the array is growing.

I then inject my service into something else (in this case an $http interceptor function) and use a service method to return the array, but each time I get an empty array.

I thought the way this worked is that all config blocks ran first and that the $http call which is being intercepted is happening way after that, so the array should be full of APIs by the time it's intercepted.

Anyway, here's some code

angular.module('authModule').provider('authService', function(){

    var _apis = [];

    return({
        addApi: addApi,
        $get: instantiateAuth
    });

    function addApi(newApi){
        _apis.push(newApi);
        console.log("API added", _apis);
    }

    function instantiateAuth() {
        return({
            getApis: function(){
                console.log("Getting APIs", _apis);
                return _apis;
            }
        });
    }

})


.config(function($httpProvider){

    $httpProvider.interceptors.push(function($log, $rootScope, $q) {
        return {
            request: function(config) {
                var injector = angular.injector(['ng', 'authModule']);
                var authService = injector.get('authService');
                console.log("apis", authService.getApis());
            }
        };
    });

});

And an example config block

angular.module('myModule').config(function ($provide, authServiceProvider) {

    authServiceProvider.addApi({
        url: 'https://apiurl.com',
        other: 'stuff'
    });

    authServiceProvider.addApi({
        url: 'https://apiurl2.com',
        other: 'stuff'
    });

});

So, each time the appApi method is called in a config block (twice here), this line outputs the array console.log("API added", _apis); and it correctly outputs 1 item after the first call and two items after the second call.

When this code - authService.getApis() - fires the first time an HTTP call is intercepted, it logs an empty array to the console.

Any help would really be appreciated.

EDIT:

The problem seems to be this line

var injector = angular.injector(['ng', 'authModule']);

My provider seems to be reset/recreated each time this happens, so maybe I'm misunderstanding how to use the injector. I was originally just injecting my authService the normal way in the function parameters but I was getting a circular dependency (my auth service needs to open a modal window, but angular-ui modals rely on the http service and my http calls are being intercepted to check with my auth service that the user is authenticated :( )

4

1 に答える 1

3

はい、angular.injector(['ng', 'authModule'])基本的に新しいインジェクター インスタンス (平たく言えばアプリケーション インスタンス) を作成します。

angular.injector(['authModule']) !== `angular.injector(['authModule'])

ngモジュールはデフォルトでロードされるため、明示的に指定する必要はありません。また、シングルトン サービスは、同じインジェクター インスタンス内でのみシングルトンになります。

injector.get('authService') === injector.get('authService');

しかし

angular.injector(['authModule']).get('authService') !== `angular.injector(['authModule']).get('authService')

現在のインジェクター インスタンスを再利用するには (ほとんどすべての状況で望ましい動作です)、$injectorサービスを使用する必要があります。

$httpProvider.interceptors.push(function($log, $rootScope, $q, $injector) {
    return {
        request: function(config) {
            var authService = $injector.get('authService');
        }
    };
});

$injector.get循環依存関係を回避するための既知の簡単なソリューションです。

于 2016-04-05T20:44:53.810 に答える