Voici un Plunk qui fait ce que vous voulez: http://plnkr.co/edit/TTlbSv?p=preview
L'idée est que vous travaillez directement avec les promesses et leurs fonctions "alors" pour manipuler et accéder aux réponses renvoyées de manière asynchrone.
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;
});
});
Voici une version légèrement plus compliquée qui met en cache la demande afin que vous ne la fassiez que la première fois ( 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()
plusieurs fois depuis différents contrôleurs, comment organiseriez-vous le service pour qu'il ne fasse$http.get()
que la première demande, et toutes les demandes suivantes renvoient simplement un tableau d'objets locaux qui est défini lors du premier appel àmyService.async()
. En d'autres termes, je veux éviter les demandes multiples et inutiles au service JSON, alors que vraiment je n'ai besoin que d'en faire une.$scope.data = myService.async()
directement dans le contrôleur.Que ce soit simple. C'est aussi simple que
promise
dans votre service (pas besoin d'utiliserthen
en service)then
dans votre contrôleurDémo. http://plnkr.co/edit/cbdG5p?p=preview
la source
app.factory
, et dans votre code, c'estapp.service
. C'est supposéapp.factory
dans ce cas.Parce qu'il est asynchrone, le
$scope
obtient les données avant la fin de l'appel ajax.Vous pouvez utiliser
$q
dans votre service pour le créerpromise
et le rendre au contrôleur, et le contrôleur obtiendra le résultat dans l'then()
appel contrepromise
.A votre service,
Ensuite, dans votre contrôleur:
la source
this.async = function() {
etthis.getData = function() {return data}
? J'espère que vous comprenez ce que je veux diredeffered = $q.defer()
à l'intérieur de myService.async si je veux appeler myService.async () deux fois ou plus$q.defer
car le$http
service renvoie déjà une promesse. La promesse retournée se bloquera si le$http
retourne une erreur. De plus, les méthodes.success
et.error
sont obsolètes et ont été supprimées d'AngularJS 1.6 .tosh shimayama a une solution mais vous pouvez simplifier beaucoup si vous utilisez le fait que $ http renvoie des promesses et que les promesses peuvent renvoyer une valeur:
Une petite démonstration en coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Votre plunker mis à jour avec ma méthode: http://plnkr.co/edit/mwSZGK?p=preview
la source
Une bien meilleure façon, je pense, serait quelque chose comme ceci:
Un service:
Et dans le contrôleur, vous pouvez simplement utiliser:
Angular mettra automatiquement le résolu
awesomeFruits
dans le$scope.fruits
.la source
J'ai eu le même problème, mais lorsque je surfais sur Internet, j'ai compris que $ http renvoyait par défaut une promesse, alors je pouvais l'utiliser avec "puis" après avoir renvoyé les "données". regardez le code:
la source
Lorsque vous liez l'interface utilisateur à votre tableau, vous devez vous assurer de mettre à jour ce même tableau directement en définissant la longueur sur 0 et en poussant les données dans le tableau.
Au lieu de cela (qui définit une référence de tableau différente à
data
laquelle votre interface utilisateur ne sera pas au courant):essaye ça:
Voici un violon qui montre la différence entre définir un nouveau tableau et vider et en ajouter un existant. Je n'ai pas pu faire fonctionner votre plnkr mais j'espère que cela fonctionne pour vous!
la source
angular.copy(d, data)
fonctionnera également. Lorsqu'une destination est fournie à la méthode copy (), elle supprimera d'abord les éléments de la destination, puis copiera les nouveaux à partir de la source.À ce sujet, j'ai rencontré un problème similaire, mais pas avec get ou post créé par Angular mais avec une extension faite par un tiers (dans mon cas, Chrome Extension).
Le problème que j'ai rencontré est que l'extension Chrome ne reviendra pas
then()
, je n'ai donc pas pu le faire de la manière indiquée dans la solution ci-dessus, mais le résultat est toujours asynchrone.Donc ma solution est de créer un service et de procéder à un rappel
Puis dans mon contrôleur
J'espère que cela peut aider les autres à résoudre le même problème.
la source
J'ai lu http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS nous permet de rationaliser la logique de notre contrôleur en plaçant une promesse directement sur la portée, plutôt que de remettre manuellement la résolution valeur dans un rappel réussi.]
si simple et pratique :)
J'espère que cette aide
la source
defrred.promise
n'est pas une fonction.$scope.items = Data.getData();
est déconseillée dans AnglularJe n'aime vraiment pas le fait que, en raison de la façon "prometteuse" de faire les choses, le consommateur du service qui utilise $ http doit "savoir" comment décompresser la réponse.
Je veux juste appeler quelque chose et extraire les données, comme à l'ancienne
$scope.items = Data.getData();
, qui est maintenant obsolète .J'ai essayé pendant un certain temps et je n'ai pas trouvé de solution parfaite, mais voici mon meilleur coup ( Plunker ). Cela peut être utile à quelqu'un.
Puis contrôleur:
Les défauts que je peux déjà repérer sont
getData
ne peut accepter leobj
paramètre que sous la forme d'un objet (bien qu'il puisse également accepter un tableau), ce qui ne sera pas un problème pour de nombreuses applications, mais c'est une limitation douloureuse$scope.data
avec= {}
pour en faire un objet (essentiellement ce qui$scope.clearData()
fait ci-dessus), ou= []
pour un tableau, ou cela ne fonctionnera pas (nous devons déjà supposer quelque chose sur les données qui arrivent). J'ai essayé de faire cette étape de préparation INgetData
, mais pas de chance.Néanmoins, il fournit un modèle qui supprime le passe-partout "promettre le déballage" du contrôleur, et peut être utile dans les cas où vous souhaitez utiliser certaines données obtenues à partir de $ http à plusieurs endroits tout en le maintenant SEC.
la source
En ce qui concerne la mise en cache de la réponse en service, voici une autre version qui semble plus simple que ce que j'ai vu jusqu'à présent:
ce service renverra soit les données mises en cache, soit
$http.get
;la source
Veuillez essayer le code ci-dessous
la source