style div attribute javascript angularjs angular-http

javascript - div - tags html



Procesando $ respuesta http en servicio (12)

Recientemente publiqué una descripción detallada del problema que estoy enfrentando here en SO. Como no pude enviar una solicitud real de $http , utilicé el tiempo de espera para simular un comportamiento asíncrono. El enlace de datos de mi modelo para ver funciona correctamente, con la ayuda de @Gloopy

Ahora, cuando uso $http lugar de $timeout (probado localmente), pude ver que la solicitud asíncrona fue exitosa y los data se llenaron con la respuesta json en mi servicio. Pero, mi punto de vista no se está actualizando.

actualizado Plunkr here


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 los data que su UI no conocerá):

myService.async = function() { $http.get(''test.json'') .success(function (d) { data = d; }); };

prueba esto:

myService.async = function() { $http.get(''test.json'') .success(function (d) { data.length = 0; for(var i = 0; i < d.length; i++){ data.push(d[i]); } }); };

Aquí hay un violín que muestra la diferencia entre configurar una nueva matriz y vaciarla y agregarla a una existente. ¡No pude hacer funcionar tu plnkr pero espero que esto funcione para ti!


Aquí hay un Plunk que hace lo que quieres: http://plnkr.co/edit/TTlbSv?p=preview

La idea es que trabaje directamente con promesas y sus funciones "a continuación" para manipular y acceder a las respuestas devueltas de forma asíncrona.

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, así que solo la haces por 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; }); }; });


Debido a que es asíncrono, $scope obtiene los datos antes de que se complete la llamada ajax.

Podría usar $q en su servicio para crear una promise y devolvérsela al controlador, y el controlador obtiene el resultado dentro de then() llamar contra promise .

En su servicio,

app.factory(''myService'', function($http, $q) { var deffered = $q.defer(); var data = []; var myService = {}; myService.async = function() { $http.get(''test.json'') .success(function (d) { data = d; console.log(d); deffered.resolve(); }); return deffered.promise; }; myService.data = function() { return data; }; return myService; });

Luego, en su controlador:

app.controller(''MainCtrl'', function( myService,$scope) { myService.async().then(function() { $scope.data = myService.data(); }); });


En lo que respecta al almacenamiento en caché de la respuesta en el servicio, aquí hay otra versión que parece más sencilla de lo que he visto hasta ahora:

App.factory(''dataStorage'', function($http) { var dataStorage;//storage for cache return (function() { // if dataStorage exists returned cached version return dataStorage = dataStorage || $http({ url: ''your.json'', method: ''GET'', cache: true }).then(function (response) { console.log(''if storage don/'t exist : '' + response); return response; }); })(); });

este servicio devolverá los datos en caché o $http.get ;

dataStorage.then(function(data) { $scope.data = data; },function(e){ console.log(''err: '' + e); });


En relación con esto pasé por un problema similar, pero no con Get o Post realizado por Angular sino con una extensión hecha por un tercero (en mi caso, Chrome Extension).
El problema al que me enfrenté es que la extensión de Chrome no regresaría then() por lo que no pude hacerlo de la forma en la solución anterior, pero el resultado sigue siendo asíncrono.
Así que mi solución es crear un servicio y proceder a una devolución de llamada

app.service(''cookieInfoService'', function() { this.getInfo = function(callback) { var model = {}; chrome.cookies.get({url:serverUrl, name:''userId''}, function (response) { model.response= response; callback(model); }); }; });

Entonces en mi control

app.controller("MyCtrl", function ($scope, cookieInfoService) { cookieInfoService.getInfo(function (info) { console.log(info); }); });

Espero que esto pueda ayudar a otros a obtener el mismo problema.


He leído http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS nos permite simplificar nuestra lógica de 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 :)

var app = angular.module(''myApp'', []); app.factory(''Data'', function($http,$q) { return { getData : function(){ var deferred = $q.defer(); var promise = $http.get(''./largeLoad'').success(function (response) { deferred.resolve(response); }); // Return the promise to the controller return deferred.promise; } } }); app.controller(''FetchCtrl'',function($scope,Data){ $scope.items = Data.getData(); });

Espero que esto ayude


Que sea sencillo. Es tan simple como

  1. promise devolución en su servicio (no es necesario utilizarla en el servicio)
  2. Utilízalo then en tu controlador.

Manifestación. http://plnkr.co/edit/cbdG5p?p=preview

var app = angular.module(''plunker'', []); app.factory(''myService'', function($http) { return { async: function() { return $http.get(''test.json''); //1. this returns promise } }; }); app.controller(''MainCtrl'', function( myService,$scope) { myService.async().then(function(d) { //2. so you can use .then() $scope.data = d; }); });


Realmente no me gusta el hecho de que, debido a la forma "prometedora" de hacer las cosas, el consumidor del servicio que utiliza $ http tiene que "saber" cómo desempaquetar la respuesta.

Solo quiero llamar algo y obtener los datos, de forma similar a la antigua $scope.items = Data.getData(); camino, 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.

app.factory(''myService'', function($http) { var _data; // cache data rather than promise var myService = {}; myService.getData = function(obj) { if(!_data) { $http.get(''test.json'').then(function(result){ _data = result.data; console.log(_data); // prove that it executes once angular.extend(obj, _data); }); } else { angular.extend(obj, _data); } }; return myService; });

Entonces el controlador:

app.controller(''MainCtrl'', function( myService,$scope) { $scope.clearData = function() { $scope.data = Object.create(null); }; $scope.getData = function() { $scope.clearData(); // also important: need to prepare input to getData as an object myService.getData($scope.data); // **important bit** pass in object you want to augment }; });

Los defectos que ya puedo detectar son

  • Debe pasar el objeto al que desea agregar los datos, que no es un patrón intuitivo o común en Angular
  • getData solo puede aceptar el parámetro obj en la forma de un objeto (aunque también puede aceptar una matriz), que no será un problema para muchas aplicaciones, pero es una limitación dolorosa
  • $scope.data preparar el objeto de entrada $scope.data con = {} para convertirlo en un objeto (esencialmente lo que $scope.clearData() hace arriba), o = [] para una matriz, o no funcionará (nosotros '' Ya estoy teniendo que asumir algo acerca de lo que vienen los datos). Traté de hacer este paso de preparación EN getData , pero no getData suerte.

Sin embargo, proporciona un patrón que elimina la placa de la caldera de "promesa de desempaquetado" del controlador y puede ser útil en los casos en los que desee utilizar ciertos datos obtenidos de $ http en más de un lugar y mantenerlo en SECO.


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:

app.factory(''myService'', function($http, $q) { myService.async = function() { return $http.get(''test.json'') .then(function (response) { var data = reponse.data; console.log(data); return data; }); }; return myService; }); app.controller(''MainCtrl'', function( myService,$scope) { $scope.asyncData = myService.async(); $scope.$watch(''asyncData'', function(asyncData) { if(angular.isDefined(asyncData)) { // Do something with the returned data, angular handle promises fine, you don''t have to reassign the value to the scope if you just want to use it with angular directives } }); });

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


Tuve el mismo problema, pero cuando estaba navegando en Internet entendí que $ http devolvía de forma predeterminada una promesa, luego podía usarlo con "luego" después de devolver los "datos". mira el código:

app.service(''myService'', function($http) { this.getData = function(){ var myResponseData = $http.get(''test.json'').then(function (response) { console.log(response);. return response.data; }); return myResponseData; } }); app.controller(''MainCtrl'', function( myService, $scope) { // Call the getData and set the response "data" in your scope. myService.getData.then(function(myReponseData) { $scope.data = myReponseData; }); });


Una manera mucho mejor creo que sería algo como esto:

Servicio:

app.service(''FruitsManager'',function($q){ function getAllFruits(){ var deferred = $q.defer(); ... // somewhere here use: deferred.resolve(awesomeFruits); ... return deferred.promise; } return{ getAllFruits:getAllFruits } });

Y en el controlador puedes simplemente usar:

$scope.fruits = FruitsManager.getAllFruits();

Angular colocará automáticamente los awesomeFruits resueltos en $scope.fruits .


Por favor intente el siguiente código

Puede dividir el controlador (PageCtrl) y el servicio (dataService)

''use strict''; (function () { angular.module(''myApp'') .controller(''pageContl'', [''$scope'', ''dataService'', PageContl]) .service(''dataService'', [''$q'', ''$http'', DataService]); function DataService($q, $http){ this.$q = $q; this.$http = $http; //... blob blob } DataService.prototype = { getSearchData: function () { var deferred = this.$q.defer(); //initiating promise this.$http({ method: ''POST'',//GET url: ''test.json'', headers: { ''Content-Type'': ''application/json'' } }).then(function(result) { deferred.resolve(result.data); },function (error) { deferred.reject(error); }); return deferred.promise; }, getABCDATA: function () { } }; function PageContl($scope, dataService) { this.$scope = $scope; this.dataService = dataService; //injecting service Dependency in ctrl this.pageData = {}; //or []; } PageContl.prototype = { searchData: function () { var self = this; //we can''t access ''this'' of parent fn from callback or inner function, that''s why assigning in temp variable this.dataService.getSearchData().then(function (data) { self.searchData = data; }); } } }());