Подтвердить что ты не робот

Несколько вызовов Ajax при авторизации приложения angular

Приложение имеет два типа ролей: "adam" и "eve". Пользователь может иметь одну или другую роль.

Angular для получения ролей:

app.factory("AuthService",function($http, $q){
    var user = undefined;
    return {
        getRoles : function(){
            var deferred = $q.defer();
            if(user !== undefined){
                deferred.resolve(user.auth);
            }else{
                $http.get("./rest/auth", {
                }).then(function(result){
                    user = result.data;
                    deferred.resolve(user.auth);
                });
            }
            return deferred.promise;
        }
    };
});

Маршрутизация выполняется следующим образом:

myApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when("/adam", {
            templateUrl: 'templates/adam.html',
            controller: 'AController'
        })
        .when("/eve", {
            templateUrl: 'templates/eve.html',
            controller: 'BController'
        })
        .when("/", {
            resolve: {
                load : function($q, $location, AuthService){
                    var defer = $q.defer();
                    AuthService.getRoles().then(function(data){
                        if(data === 'adam'){
                            $location.path('/adam');
                        }else{
                            $location.path('/eve');
                        }
                        defer.resolve();
                    });
                    return defer.promise;
                }
            }
        })
        .otherwise({ redirectTo: '/' });;
}]);

Мне нужно получить роли в контроллере, а также выполнить определенную операцию. Код контроллера:

angular.element(document).ready(function () {
    AuthService.getRoles().then(function(data){
        // some operation
    });
});

При навигации по '/' ajax вызывается дважды, так как функция разрешения и контроллера вызывает AuthService.getRoles(). Как я могу перестроить код так, чтобы ajax вызывался только один раз?

4b9b3361

Ответ 1

Я бы сменил ваш factory на что-то подобное, чтобы они вступили в одно и то же обещание:

app.factory("AuthService", function ($http, $q) {
    var userPromise;
    return {
        getRoles : function () {
            if(!userPromise){
                userPromise = $http.get("./rest/auth", {}).then(function(result){
                    return result.data;
                });
            }

            return userPromise;
        }
    };
});

Это создает обещание, если оно не установлено, чтобы получить данные. Каждый вызов после этого будет иметь обещание, созданное таким образом, что оно будет просто подключаться к первому и не выполнять последующие вызовы. Причина, по которой он не работает для вас, заключается в том, что ваш пользователь получает только после $http.get, поэтому во второй раз он все еще видит его как undefined.

Ответ 2

Я не понимаю:

Вы не могли бы просто сделать (в своем контроллере):

angular.element(document).ready(function () {
    if($route.current !== '/'){
      AuthService.getRoles().then(function(data){
      // some operation
    }
  });
});

Это может быть undefined, но вы получите эту идею (возможно, emit- > broadcast- > on даст вам параметры маршрута надежно. Может потребоваться время ожидания $. ($ timeout 0 не грязно в angular он просто устанавливает последнее в очереди).

Ответ 3

вы можете попробовать

Factory

app.factory("AuthService", function ($http, $q) {
    var user = undefined;
    var authSvc = null;

    return function () {
        if (!app.isSvcInstance) {
            authSvc = null;
            this.getRoles = function () {
                var deferred = $q.defer();
                if (user !== undefined) {
                    deferred.resolve(user.auth);
                } else {
                    $http.get("./rest/auth", {

                    }).then(function (result) {
                        user = result.data;
                        deferred.resolve(user.auth);
                    });
                }
                return deferred.promise;
            };
            authSvc = this;
            return this;
        }
        return authSvc;
    };
});

контроллер

angular.element(document).ready(function () {
    app.isSvcInstance = true;
    var auth = new AuthService();
    auth.getRoles().then(function (data) {
        // some operation
    });
});

Alternative

app.factory("AuthService", function ($http, $q, $cacheFactory) {

            var cacheSvc = $cacheFactory("myCache");

            return {
                getRoles: function () {
                    var cacheFac = cacheSvc.get("authCache");
                    var deferred = $q.defer();
                    if (!cacheFac || cacheFac.length === 0) {
                        $http.get("./rest/auth", {

                        }).then(function (result) {
                            cacheSvc.put("authCache", result.data);
                            deferred.resolve(result.data);
                        });
                    } else {
                        deferred.resolve(cacheSvc.get("authCache"));
                    }
                    return deferred.promise;
                }
            };
        });

Ответ 4

вы можете проверить функцию $q.all

В основном он объединяет несколько promises в одном