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
promise
en su servicio (no es necesario usarlothen
en el servicio)then
en su controladorManifestación. http://plnkr.co/edit/cbdG5p?p=preview
fuente
app.factory
, y en su código estáapp.service
. Se suponeapp.factory
en este caso.Como es asíncrono,
$scope
obtiene los datos antes de que se complete la llamada ajax.Puede usarlo
$q
en su servicio para crearpromise
y 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.defer
ya que el$http
servicio ya devuelve una promesa. La promesa devuelta se suspenderá si$http
devuelve un error. Además, los métodos.success
y.error
está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
awesomeFruits
en 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
data
que 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.promise
no 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
getData
solo puede aceptar elobj
pará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.data
con= {}
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