Aquí hay un Plunk que hace lo que quieres: http://plnkr.co/edit/TTlbSv?p=preview
La idea es que trabaje directamente con las promesas y sus funciones "entonces" para manipular y acceder a las respuestas devueltas asincrónicamente.
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
Aquí hay una versión un poco más complicada que almacena en caché la solicitud para que solo la haga la primera vez ( http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview ):
app.factory('myService', function($http) {
var promise;
var myService = {
async: function() {
if ( !promise ) {
// $http returns a promise, which has a then function, which also returns a promise
promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
}
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = {};
};
$scope.getData = function() {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
};
});
then?myService.async()múltiples veces desde varios controladores, ¿cómo organizaría el servicio para que solo se haga$http.get()para la primera solicitud, y todas las solicitudes posteriores solo devuelven una matriz de objetos local que se establece en la primera llamadamyService.async()? En otras palabras, quiero evitar múltiples solicitudes innecesarias al servicio JSON, cuando realmente solo necesito hacer una.$scope.data = myService.async()directamente en el controlador.Que sea simple. Es tan simple como
promiseen su servicio (no es necesario usarlothenen el servicio)thenen su controladorManifestación. http://plnkr.co/edit/cbdG5p?p=preview
fuente
app.factory, y en su código estáapp.service. Se suponeapp.factoryen este caso.Como es asíncrono,
$scopeobtiene los datos antes de que se complete la llamada ajax.Puede usarlo
$qen su servicio para crearpromisey devolverlo al controlador, y el controlador obtendrá el resultado dentro de lathen()llamada en contrapromise.A su servicio
Luego, en su controlador:
fuente
this.async = function() {ythis.getData = function() {return data}? Espero que entiendas lo que quiero decirdeffered = $q.defer()dentro de myService.async si quiero llamar a myService.async () dos o más veces$q.deferya que el$httpservicio ya devuelve una promesa. La promesa devuelta se suspenderá si$httpdevuelve un error. Además, los métodos.successy.errorestán en desuso y se han eliminado de AngularJS 1.6 .tosh shimayama tiene una solución, pero puede simplificar mucho si usa el hecho de que $ http devuelve promesas y que las promesas pueden devolver un valor:
Una pequeña demostración en coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Su plunker actualizado con mi método: http://plnkr.co/edit/mwSZGK?p=preview
fuente
Una forma mucho mejor creo que sería algo como esto:
Servicio:
Y en el controlador simplemente puede usar:
Angular pondrá automáticamente el resuelto
awesomeFruitsen el$scope.fruits.fuente
Tuve el mismo problema, pero cuando estaba navegando en Internet entendí que $ http devuelve por defecto una promesa, luego podría usarlo con "luego" después de devolver los "datos". mira el código:
fuente
Al vincular la interfaz de usuario a su matriz, querrá asegurarse de actualizar esa misma matriz directamente estableciendo la longitud en 0 e insertando los datos en la matriz.
En lugar de esto (que establece una referencia de matriz diferente a la
dataque su IU no sabrá):prueba esto:
Aquí hay un violín que muestra la diferencia entre configurar una nueva matriz frente a vaciar y agregar una existente. No pude hacer que tu plnkr funcionara, pero espero que esto funcione para ti.
fuente
angular.copy(d, data)También funcionará. Cuando se suministra un destino al método copy (), primero eliminará los elementos del destino y luego copiará los nuevos del origen.Relacionado con esto, pasé por un problema similar, pero no con get o post hecho por Angular sino con una extensión hecha por un tercero (en mi caso, Chrome Extension).
El problema que enfrenté es que la extensión de Chrome no volverá,
then()por lo que no pude hacerlo de la manera anterior, pero el resultado sigue siendo asíncrono.Entonces, mi solución es crear un servicio y proceder a una devolución de llamada
Entonces en mi controlador
Espero que esto pueda ayudar a otros a tener el mismo problema.
fuente
He leído http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS nos permite simplificar la lógica de nuestro controlador al hacer una promesa directamente en el alcance, en lugar de entregar manualmente el resuelto valor en una devolución de llamada exitosa.]
tan simple y práctico :)
Espero que esto ayude
fuente
defrred.promiseno es una función.$scope.items = Data.getData();está en desuso en AnglularRealmente no me gusta el hecho de que, debido a la forma "prometedora" de hacer las cosas, el consumidor del servicio que usa $ http tiene que "saber" cómo desempaquetar la respuesta.
Solo quiero llamar a algo y obtener los datos, similar a la
$scope.items = Data.getData();forma anterior, que ahora está en desuso .Lo intenté por un tiempo y no encontré una solución perfecta, pero aquí está mi mejor oportunidad ( Plunker ). Puede ser útil para alguien.
Entonces controlador:
Las fallas que ya puedo detectar son
getDatasolo puede aceptar elobjparámetro en forma de un objeto (aunque también podría aceptar una matriz), lo que no será un problema para muchas aplicaciones, pero es una limitación importante$scope.datacon= {}para que sea un objeto (en esencia, lo que$scope.clearData()lo hace más arriba), o= []de una matriz, o de lo contrario no funciona (ya estamos tener que asumir algo acerca de lo que está llegando datos). Traté de hacer este paso de preparacióngetData, pero no tuve suerte.Sin embargo, proporciona un patrón que elimina la repetitiva "promesa de desenvolver" del controlador, y podría ser útil en los casos en que desee utilizar ciertos datos obtenidos de $ http en más de un lugar mientras lo mantiene SECO.
fuente
En cuanto al almacenamiento en caché de la respuesta en el servicio, aquí hay otra versión que parece más sencilla que la que he visto hasta ahora:
este servicio devolverá los datos en caché o
$http.get;fuente
Por favor, intente el siguiente código
fuente