Служба загрузки AngularJS затем вызывает контроллер и визуализирует

Моя проблема в том, что мне нужна служба, загруженная до того, как контроллер будет вызван, и шаблон получит визуализацию. http://jsfiddle.net/g75XQ/2/

Html:

<div ng-app="app" ng-controller="root">
    <h3>Do not render this before user has loaded</h3>            
    {{user}}
</div>
​

JavaScript:

angular.module('app', []).
factory('user',function($timeout,$q){
    var user = {};            
    $timeout(function(){//Simulate a request
        user.name = "Jossi";
    },1000);
    return user;
}).
controller('root',function($scope,user){

    alert("Do not alert before user has loaded");
    $scope.user = user;

});
​

Ответ 1

Вы можете отложить init angular с помощью ручная инициализация вместо автоматического init с атрибутом ng-app.

// define some service that has `$window` injected and read your data from it
angular.service('myService', ['$window', ($window) =>({   
      getData() {
          return $window.myData;
      }
}))    

const callService = (cb) => {
   $.ajax(...).success((data)=>{
         window.myData = data;
         cb(data)
   })
}

// init angular app 
angular.element(document).ready(function() {
       callService(function (data) {
          doSomething(data);
          angular.bootstrap(document);
       });
});

где callService - ваша функция, выполняющая вызов AJAX и принимающая обратный вызов успеха, который будет запускать angular приложение.

Также проверьте директиву ngCloak, так как это возможно все, что вам нужно.

В качестве альтернативы при использовании ngRoute вы можете использовать свойство resolve, для этого вы можете увидеть ответ @honkskillet

Ответ 2

даже лучше, чем ручная загрузка (что не всегда является плохой идеей).

angular.module('myApp', ['app.services'])
   .run(function(myservice) {
      //stuff here.
   });

Ответ 3

Как я уже сказал в комментариях, было бы намного проще обрабатывать выгруженное состояние в вашем контроллере, вы можете извлечь выгоду из $q, чтобы сделать это очень просто: http://jsfiddle.net/g/g75XQ/4/

если вы хотите что-то сделать в контроллере, когда пользователь загружен: http://jsfiddle.net/g/g75XQ/6/

EDIT: Чтобы отложить изменение маршрута до загрузки некоторых данных, посмотрите на этот ответ: Отмена изменения маршрута AngularJS до загрузки модели для предотвращения мерцания

Ответ 4

Правильный способ достижения этого - использовать свойство разрешения в определении маршрутов: см. http://docs.angularjs.org/api/ngRoute.$routeProvider

затем создайте и верните обещание, используя службу $q; также используйте $http, чтобы сделать запрос и ответ, разрешите обещание.

Таким образом, когда маршрут будет разрешен и контроллер будет загружен, результат обещания будет уже доступен, и не будет мерцания.

Ответ 5

Вы можете использовать решение в .config $routeProvider. Если обещание возвращается (как оно есть здесь), маршрут не будет загружаться, пока он не будет разрешен или отклонен. Кроме того, возвращаемое значение будет доступно для ввода в контроллер (в данном случае Somert).

angular.module('somertApp')
  .config(function($routeProvider) {
    $routeProvider
      .when('/home/:userName', {
        /**/
        resolve: {
          Somert: function($q, $location, Somert) {
            var deferred = $q.defer();
            Somert.get(function(somertVal) {
              if (somertVal) {
                deferred.resolve(somertVal);
              } else {
                deferred.resolve();
                $location.path('/error/'); //or somehow handle not getting
              }
            });
            return deferred.promise;
          },
        },
      });
  });

Ответ 6

Есть несколько способов, некоторые более продвинутые, чем другие, но в вашем случае ng-hide делает трюк. См. http://jsfiddle.net/roytruelove/g75XQ/3/