Почему обещание не работает должным образом в AngularJS

В моем приложении AngularJS при каждом запросе на изменение страницы, которую я запускаю:

    $rootScope.$on('$locationChangeStart', function (event, next, current) {
        var user;
        $http.get('/api/Authentication/UserAuthenticated').then(function (data) {
        console.log("call");
         user = data.data;
       });   
      console.log("end of call");
    });

Когда я запускаю приложение и проверяю, что происходит, я вижу в консоли, что «конец вызова» возвращается до console.log("call");, что означает, что пользователь не установлен. Это означает, что если я хочу проверить, вошел ли пользователь в систему при изменении маршрута, пользователь будет неопределенным.

Как мне сделать запрос Angular run-> http и только потом продолжить?


person Timsen    schedule 26.02.2014    source источник
comment
Это связано не с promises, а с $http, выполняющим асинхронный вызов. Поскольку вызов get является асинхронным, "end of call" всегда будет отображаться первым.   -  person Davin Tryon    schedule 26.02.2014
comment
Для такого рода задач вы должны использовать свойство resolve конфигурации маршрута.   -  person dfsq    schedule 26.02.2014
comment
Можете ли вы привести пример того, как я могу реализовать это с помощью решения? Я вижу, что документы, которые разрешают, заставят рут ждать, пока все HTTP-запросы не будут выполнены.   -  person Timsen    schedule 26.02.2014
comment
Пожалуйста, проверьте мой ответ.   -  person Ramesh Rajendran    schedule 26.02.2014
comment
Это может быть полезно: stackoverflow.com/questions/16849050   -  person AlwaysALearner    schedule 26.02.2014


Ответы (2)


Я немного неправильно понял вопрос. Вы можете позволить $routeProvider выполнить обещание $http:

var app = angular.module("myApp");

app.config(["$routeProvider", function($routeProvider) {
  $routeProvider.when("/",{
    templateUrl: "myTemplate.html",
    controller: "MyCtrl",
    resolve: {
      user: ["$http", "$q", function($http, $q) {
        var deferred = $q.defer();
        $http.get('/api/Authentication/UserAuthenticated').success(function(data){
           deferred.resolve(data.data);
        }).error(function(error) {
           deferred.resolve(false);
        });
        return deferred.promise;
      }]
    }
  });
}]);

Если код для извлечения пользовательских данных слишком сложен, вы можете создать для него службу и внедрить эту службу в функцию $routeProvider resolve.

В вашем контроллере вы просто вводите обещание (которое будет разрешено):

app.controller("MyCtrl",["$scope","user", function($scope, user) {
   if (!user) {
      alert("User not found");
   }
...
}]);
person asgoth    schedule 26.02.2014
comment
$scope.user = данные.данные; будет установлено поздно, поэтому изменение местоположения пройдет до того, как http получит ответ. - person Timsen; 26.02.2014
comment
Последний вопрос: как мне выбрать пользовательский параметр на моем маршруте, когда я меняю местоположение? в onlocationChangestart? - person Timsen; 26.02.2014
comment
Что вы подразумеваете под «параметром пользователя». Нужна ли для запроса $http строка идентификатора пользователя (например, «12345»), которая заполняется через форму ввода? - person asgoth; 26.02.2014
comment
Я просто хочу показать всплывающее сообщение, когда пользователь неверен, и я пытаюсь проверить его в $locationChangeStart, но я не могу получить пользовательский параметр из $route - person Timsen; 26.02.2014
comment
Я немного обновил свой ответ. Вы заметите в блоке ошибок resolve(false). В вашем контроллере вы получаете false вместо user. Конечно, вам нужно будет улучшить это. - person asgoth; 26.02.2014
comment
Вам не нужно создавать новый deferred для разрешения, вы можете вернуть данные из обработчика успеха метода then, который завершит результат в новое обещание для вас и уменьшит объем необходимого кода. См.: odetocode.com/blogs/ Скотт/архив/2014/03/26/ - person OdeToCode; 29.03.2014

используйте 1_. Это работает для меня

Попробуйте этот код вместо вашего кода

$rootScope.$on('$locationChangeStart', function (event, next, current) {
$http({method: 'GET',
            url: '/api/Authentication/UserAuthenticated',                
            async: false
              }).success(function (data) {
            console.log("call");
            user = data.data;
             }
         console.log("end of call");   
 });
person Ramesh Rajendran    schedule 26.02.2014
comment
Я не проголосовал за вас, но я подозреваю, что это потому, что вы используете хакерское решение, чтобы обойти нормальное поведение. - person rg88; 26.02.2014