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

$ http-запрос перед запуском приложения AngularJS?

Чтобы определить, аутентифицирован ли сеанс пользователя, мне нужно сделать запрос $http на сервер до загрузки первого маршрута. Перед загрузкой каждого маршрута служба проверки подлинности проверяет статус пользователя и уровень доступа, который требуется для маршрута, и если пользователь не аутентифицирован для этого маршрута, он перенаправляется на страницу входа. Однако, когда приложение загружается, оно не знает пользователя, поэтому даже если у него есть аутентифицированный сеанс, он всегда будет перенаправляться на страницу входа в систему. Поэтому, чтобы исправить это, я пытаюсь сделать запрос на сервер для статуса пользователей в качестве части инициализации приложения. Проблема в том, что, очевидно, $http-вызовы асинхронны, так как я могу остановить приложение до завершения запроса?

Я очень новичок в разработке Angular и в интерфейсе в целом, поэтому моя проблема может быть неправильным пониманием javascript, а не Angular.

4b9b3361

Ответ 1

Это можно сделать с помощью resolve в вашем маршрутизаторе.

Это позволяет подождать, пока какой-нибудь promises будет разрешен до того, как контроллер будет запущен.

Цитата из документов:

resolve - {Object. =} - необязательная карта зависимостей, которая должна быть введена в контроллер. Если какая-либо из этих зависимостей promises, маршрутизатор будет ждать, пока все они будут разрешены или один будет отклонен до того, как будет создан экземпляр контроллера. Если все promises успешно разрешены, значения разрешенных promises вводятся и запускается событие $routeChangeSuccess.

Простой пример

    app.config(['$routeProvider', function($routeProvider) {
    $routeProvider.
        when('/', {templateUrl: 'home.html', controller: 'MyCtrl',resolve: {
            myVar: function($q,$http){
                var deffered = $q.defer();

                    // make your http request here and resolve its promise

                     $http.get('http://example.com/foobar')
                         .then(function(result){
                             deffered.resolve(result);
                          })

                return deffered.promise;
            }
        }}).
        otherwise({redirectTo: '/'});
}]);

myVar затем будет введен в ваш контроллер, содержащий данные обещания.

Избегание дополнительного параметра DI

Вы также можете избежать дополнительного параметра DI, возвращая службу, которую вы собираетесь вводить в любом случае:

app.config(['$routeProvider', function($routeProvider) {
        $routeProvider.
            when('/', {templateUrl: 'home.html', controller: 'MyCtrl',resolve: {
                myService: function($q,$http,myService){
                  var deffered = $q.defer();

                      /*  make your http request here
                      *   then, resolve the deffered promise with your service.
                      */

                  deffered.resolve(myService),

                  return deffered.promise;
                }
            }}).
            otherwise({redirectTo: '/'});
    }]);

Очевидно, вам нужно будет сохранять результат из вашего запроса в любом месте общей службы при выполнении подобных действий.


Посмотрите Angular Документы /routeProvider

Я узнал большую часть этого материала от этого парня в egghead.io

Ответ 2

Инкапсулируйте все свои ресурсы с помощью sessionCreator и верните обещание. После resolve затем на ваш контроллер, чтобы вы могли оставить его без определенного кода promise.

app.factory('sessionCreator', ['$http', '$q', 'urlApi',

  function ($http, $q, urlApi) {
    var deferred = $q.defer();

    $http.get(urlApi + '/startPoint').success(function(data) {
      // Do what you have to do for initialization.
      deferred.resolve();
    });

    return deferred.promise;
  }

]);

app.factory('Product', ['$resource', 'urlApi', 'sessionCreator',

  function($resource, urlApi, sessionCreator) {
    // encapsulate all yours services with `sessionCreator`
    return sessionCreator.then(function() {
      return $resource(urlApi + '/products', {}, {
        query: {method:'GET', params:{}, isArray: true}
      });
    });
  }

]);

app.config(['$routeProvider', function ($routeProvider) {

  var access = routingConfig.accessLevels;

  $routeProvider
    .when('/product', {
      templateUrl: 'views/products.html', controller: 'ProductCtrl',
      // resolve then in router configuration so you don't have to call `then()` inside your controllers
      resolve: { Product: ['Product', function(Product) { return Product; }] }
    })
    .otherwise({ redirectTo: '/' });
}]);