Служба загрузки 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/