Aqui está um Plunk que faz o que você deseja: http://plnkr.co/edit/TTlbSv?p=preview
A idéia é que você trabalhe diretamente com as promessas e suas funções "then" para manipular e acessar as respostas retornadas de forma assí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;
});
});
Aqui está uma versão um pouco mais complicada que armazena em cache a solicitação, para que você a faça apenas pela primeira 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()
várias vezes a partir de vários controladores, como você organizaria o serviço para que seja o único$http.get()
requisito para a primeira solicitação e todas as solicitações subsequentes retornem apenas uma matriz de objetos local definida na primeira chamada paramyService.async()
. Em outras palavras, desejo evitar várias solicitações desnecessárias ao serviço JSON, quando na verdade só preciso fazer uma.$scope.data = myService.async()
diretamente no controlador.Que seja simples. É tão simples quanto
promise
em seu serviço (não é necessário usá-lothen
)then
no seu controladorDemo. http://plnkr.co/edit/cbdG5p?p=preview
fonte
app.factory
, e no seu código, éapp.service
. É supostoapp.factory
neste caso.Por ser assíncrono,
$scope
está obtendo os dados antes da conclusão da chamada ajax.Você pode usar
$q
em seu serviço para criarpromise
e devolvê-lo ao controlador, e o controlador obtém o resultado dentro de umathen()
chamadapromise
.Em seu serviço,
Então, no seu controlador:
fonte
this.async = function() {
ethis.getData = function() {return data}
? Eu espero que você começa o que eu quero dizerdeffered = $q.defer()
dentro do myService.async se eu quiser chamar myService.async () duas ou mais vezes$q.defer
pois o$http
serviço já retorna uma promessa. A promessa retornada será interrompida se$http
retornar um erro. Além disso, os métodos.success
e.error
estão obsoletos e foram removidos do AngularJS 1.6 .shoshyama tem uma solução, mas você pode simplificar muito se usar o fato de que $ http retorna promessas e essas promessas podem retornar um valor:
Uma pequena demonstração no coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Seu desentupidor atualizado com o meu método: http://plnkr.co/edit/mwSZGK?p=preview
fonte
Uma maneira muito melhor eu acho que seria algo como isto:
Serviço:
E no controlador você pode simplesmente usar:
Angular colocará automaticamente o resolvido
awesomeFruits
no$scope.fruits
.fonte
Eu tinha o mesmo problema, mas quando estava navegando na internet, entendi que $ http retornava por padrão uma promessa, então eu poderia usá-lo com "then" depois de retornar os "dados". veja o código:
fonte
Ao vincular a interface do usuário à sua matriz, você deve atualizar a mesma matriz diretamente, definindo o comprimento como 0 e inserindo os dados na matriz.
Em vez disso (que define uma referência de matriz diferente para a
data
qual sua interface do usuário não saberá):tente isto:
Aqui está um violino que mostra a diferença entre definir uma nova matriz versus esvaziar e adicionar a uma existente. Não consegui que seu plnkr funcionasse, mas espero que funcione para você!
fonte
angular.copy(d, data)
também irá funcionar. Quando um destino é fornecido ao método copy (), ele primeiro exclui os elementos do destino e depois copia os novos da fonte.Relacionado a isso, passei por um problema semelhante, mas não com o get ou post feito pelo Angular, mas com uma extensão feita por terceiros (no meu caso, a extensão do Chrome).
O problema que eu enfrentei é que a extensão do Chrome não retornará,
then()
então não consegui fazê-lo da maneira acima na solução acima, mas o resultado ainda é assíncrono.Portanto, minha solução é criar um serviço e prosseguir para um retorno de chamada
Então no meu controlador
Espero que isso ajude outras pessoas a obter o mesmo problema.
fonte
Eu li http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS nos permite otimizar nossa lógica de controlador colocando uma promessa diretamente no escopo, em vez de entregar manualmente a solução resolvida valor em um retorno de chamada bem-sucedido.]
tão simples e prático :)
Espero que esta ajuda
fonte
defrred.promise
não é uma função.$scope.items = Data.getData();
é obsoleto em AnglularEu realmente não gosto do fato de que, devido à maneira "promissora" de fazer as coisas, o consumidor do serviço que usa $ http precisa "saber" sobre como descompactar a resposta.
Eu só quero chamar alguma coisa e divulgar os dados, de maneira semelhante à antiga
$scope.items = Data.getData();
, que agora está obsoleta .Tentei por um tempo e não achei uma solução perfeita, mas aqui está minha melhor chance ( Plunker ). Pode ser útil para alguém.
Então controlador:
As falhas que eu já consigo identificar são
getData
só pode aceitar oobj
parâmetro na forma de um objeto (embora também possa aceitar uma matriz), o que não será um problema para muitos aplicativos, mas é uma limitação dolorida$scope.data
com= {}
a torná-lo um objeto (essencialmente o que$scope.clearData()
faz acima), ou= []
para um array, ou não vai funcionar (já estamos tendo que assumir algo sobre os dados que entram). Eu tentei fazer este passo de preparaçãogetData
, mas sem sorte.No entanto, ele fornece um padrão que remove o clichê do controlador "promete desembrulhar" e pode ser útil nos casos em que você deseja usar determinados dados obtidos a partir de $ http em mais de um local, mantendo-o SECO.
fonte
No que diz respeito ao cache da resposta em serviço, aqui está outra versão que parece mais direta do que o que vi até agora:
esse serviço retornará os dados em cache ou
$http.get
;fonte
Por favor, tente o código abaixo
fonte