javascript - promesas - Servicio de carga AngularJS luego llamar controlador y render
promesas angular 4 (6)
Mi problema es que necesito un servicio cargado antes de que se llame al controlador y se genere la plantilla. 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;
});
En
Como dije en los comentarios, sería mucho más fácil manejar un estado descargado en su controlador, puede beneficiarse de $ q para hacer esto muy sencillo: http://jsfiddle.net/g/g75XQ/4/
si desea hacer algo en el controlador cuando se carga el usuario: http://jsfiddle.net/g/g75XQ/6/
EDITAR: para retrasar el cambio de ruta hasta que se carguen algunos datos, observe esta respuesta: Retrasar el cambio de ruta de AngularJS hasta que se cargue el modelo para evitar el parpadeo
Hay algunas formas, algunas más avanzadas que otras, pero en su caso ng-hide hace el truco. Ver http://jsfiddle.net/roytruelove/g75XQ/3/
La forma correcta de lograrlo es usar la propiedad de resolución en la definición de rutas: consulte http://docs.angularjs.org/api/ngRoute.$routeProvider
luego crea y devuelve una promesa usando el servicio $ q; También use $ http para realizar la solicitud y, en respuesta, resuelva la promesa.
De esa manera, cuando se resuelva la ruta y se cargue el controlador, el resultado de la promesa ya estará disponible y no se producirá ningún parpadeo.
Puede aplazar el inicio de la aplicación angular utilizando la inicialización manual , en lugar del inicio automático con el atributo 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);
});
});
donde callService
es su función realizando una llamada AJAX y aceptando una devolución de llamada exitosa, que iniciará la aplicación angular.
También ngCloak
ver la directiva ngCloak
, ya que quizás sea todo lo que necesitas.
Alternativamente, al usar ngRoute puede usar la propiedad de resolve
, para eso puede ver la respuesta de @honkskillet
Puede usar resolver en el .config $ routeProvider. Si se devuelve una promesa (como está aquí), la ruta no se cargará hasta que se resuelva o rechace. Además, el valor de retorno estará disponible para inyectarse en el controlador (en este caso, 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;
},
},
});
});
incluso mejor que el arranque manual (lo que tampoco es siempre una mala idea).
angular.module(''myApp'', [''app.services''])
.run(function(myservice) {
//stuff here.
});