Como esperar até que a resposta venha do pedido $ http, em angularjs?

Estou usando alguns dados que são de um serviço RESTful em várias páginas. Então estou usando fábricas angulares para isso. Então, eu precisei obter os dados uma vez no servidor e toda vez que estou obtendo os dados com esse serviço definido. Assim como as variables ​​globais. Aqui está o exemplo:

var myApp = angular.module('myservices', []); myApp.factory('myService', function($http) { $http({method:"GET", url:"/my/url"}).success(function(result){ return result; }); }); 

No meu controlador eu estou usando este serviço como:

 function myFunction($scope, myService) { $scope.data = myService; console.log("data.name"+$scope.data.name); } 

Está funcionando bem para mim como por minhas exigências. Mas o problema aqui é que, quando eu recarreguei na minha página, o serviço será chamado novamente e os pedidos de servidor. Se entre alguma outra function executa que é dependente do “serviço definido”, está dando o erro como “algo” é indefinido. Então, eu quero esperar no meu script até que o serviço seja carregado. Como eu posso fazer isso? Existe alguma maneira de fazer isso em angularjs?

Você deve usar promises para operações assíncronas nas quais não sabe quando elas serão concluídas. Uma promise “representa uma operação que ainda não foi concluída, mas é esperada no futuro”. ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise )

Um exemplo de implementação seria como:

 myApp.factory('myService', function($http) { var getData = function() { // Angular $http() and then() both return promises themselves return $http({method:"GET", url:"/my/url"}).then(function(result){ // What we return here is the data that will be accessible // to us after the promise resolves return result.data; }); }; return { getData: getData }; }); function myFunction($scope, myService) { var myDataPromise = myService.getData(); myDataPromise.then(function(result) { // this is only run after getData() resolves $scope.data = result; console.log("data.name"+$scope.data.name); }); } 

Edit: Em relação Sujoys comentar que O que eu preciso fazer para que a chamada myFuction () não retornará até que a function .then () termine a execução.

 function myFunction($scope, myService) { var myDataPromise = myService.getData(); myDataPromise.then(function(result) { $scope.data = result; console.log("data.name"+$scope.data.name); }); console.log("This will get printed before data.name inside then. And I don't want that."); } 

Bem, vamos supor que a chamada para getData () levou 10 segundos para ser concluída. Se a function não retornasse nada naquele tempo, ela se tornaria efetivamente um código síncrono normal e suspenderia o navegador até que fosse concluído.

Com a promise de retornar instantaneamente, o navegador está livre para continuar com outro código nesse meio tempo. Quando a promise é resolvida / falha, a chamada then () é acionada. Por isso, faz muito mais sentido, mesmo que isso torne o stream do seu código um pouco mais complexo (a complexidade é um problema comum de programação assíncrona / paralela em geral!)

para as pessoas novas para isso, você também pode usar um retorno de chamada, por exemplo:

Em seu serviço:

 .factory('DataHandler',function ($http){ var GetRandomArtists = function(data, callback){ $http.post(URL, data).success(function (response) { callback(response); }); } }) 

No seu controlador:

  DataHandler.GetRandomArtists(3, function(response){ $scope.data.random_artists = response; }); 

Eu estava tendo o mesmo problema e nenhum se isso funcionou para mim. Aqui está o que funcionou …

 app.factory('myService', function($http) { var data = function (value) { return $http.get(value); } return { data: data } }); 

e então a function que usa é …

 vm.search = function(value) { var recieved_data = myService.data(value); recieved_data.then( function(fulfillment){ vm.tags = fulfillment.data; }, function(){ console.log("Server did not send tag data."); }); }; 

O serviço não é necessário, mas acho que é uma boa prática para extensibilidade. A maior parte do que você precisará para um será para qualquer outro, especialmente ao usar APIs. De qualquer forma, espero que tenha sido útil.

FYI, isto está usando Angularfire assim pode variar um pouco para um serviço diferente ou outro uso mas deveria resolver o mesmo isse $ http tem. Eu tive esse mesmo problema apenas a solução que melhor se encaixou para mim foi combinar todos os serviços / fábricas em uma única promise no escopo. Em cada rota / visão que precisava destes serviços / etc para ser carregado eu coloquei quaisquer funções que requerem dados carregados dentro da function do controlador ie myfunct () e o app.js principal em run after auth i put

 myservice.$loaded().then(function() {$rootScope.myservice = myservice;}); 

e na visão que acabei de fazer

 ng-if="myservice" ng-init="somevar=myfunct()" 

no primeiro / parent view elemento / wrapper para que o controlador possa executar tudo dentro

 myfunct() 

sem se preocupar com promises assíncronas / problemas de ordem / fila. Espero que ajude alguém com os mesmos problemas que eu tive.