Hier ist ein Plunk, der macht, was Sie wollen: http://plnkr.co/edit/TTlbSv?p=preview
Die Idee ist, dass Sie direkt mit Versprechungen und deren "Dann" -Funktionen arbeiten, um die asynchron zurückgegebenen Antworten zu bearbeiten und darauf zuzugreifen.
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;
});
});
Hier ist eine etwas kompliziertere Version, die die Anforderung zwischenspeichert, sodass Sie sie nur beim ersten Mal erstellen ( 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()
Dienste mehrmals von verschiedenen Controllern aus aufrufen möchte , wie würden Sie den Dienst so organisieren, dass nur$http.get()
die erste Anforderung ausgeführt wird und alle nachfolgenden Anforderungen nur ein lokales Objektarray zurückgeben, das beim ersten Aufruf an festgelegt wirdmyService.async()
. Mit anderen Worten, ich möchte mehrere unnötige Anforderungen an den JSON-Dienst vermeiden, wenn ich wirklich nur eine stellen muss.$scope.data = myService.async()
direkt in der Steuerung verwenden.Lass es einfach sein. Es ist so einfach wie
promise
in Ihren Service (keine Notwendigkeit,then
im Service zu verwenden)then
in Ihrem ControllerDemo. http://plnkr.co/edit/cbdG5p?p=preview
quelle
app.factory
und in Ihrem Code ist esapp.service
. Es wirdapp.factory
in diesem Fall angenommen.Da es asynchron
$scope
ist, werden die Daten abgerufen, bevor der Ajax-Aufruf abgeschlossen ist.Sie können es
$q
in Ihrem Dienst verwenden, umpromise
es zu erstellen und an den Controller zurückzugeben, und der Controller erhält das Ergebnis innerhalb desthen()
Aufrufs gegenpromise
.In Ihrem Dienst,
Dann in Ihrem Controller:
quelle
this.async = function() {
undthis.getData = function() {return data}
? Ich hoffe du bekommst was ich meinedeffered = $q.defer()
in myService.async hinzugefügt werden, wenn ich myService.async () zwei oder mehr Mal aufrufen möchte$q.defer
da der$http
Service bereits ein Versprechen zurückgibt. Das zurückgegebene Versprechen bleibt hängen, wenn$http
ein Fehler zurückgegeben wird. Außerdem sind die Methoden.success
und.error
veraltet und wurden aus AngularJS 1.6 entfernt .tosh shimayama hat eine Lösung, aber Sie können viel vereinfachen, wenn Sie die Tatsache nutzen, dass $ http Versprechen zurückgibt und dass Versprechen einen Wert zurückgeben können:
Eine kleine Demonstration in Coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Ihr Plunker wurde mit meiner Methode aktualisiert: http://plnkr.co/edit/mwSZGK?p=preview
quelle
Ein viel besserer Weg, denke ich, wäre so etwas:
Bedienung:
Und in der Steuerung können Sie einfach verwenden:
Angular setzt das aufgelöste automatisch
awesomeFruits
in das$scope.fruits
.quelle
Ich hatte das gleiche Problem, aber als ich im Internet surfte, verstand ich, dass $ http standardmäßig ein Versprechen zurückgibt, dann könnte ich es mit "dann" verwenden, nachdem ich die "Daten" zurückgegeben habe. Schauen Sie sich den Code an:
quelle
Wenn Sie die Benutzeroberfläche an Ihr Array binden, sollten Sie sicherstellen, dass Sie dasselbe Array direkt aktualisieren, indem Sie die Länge auf 0 setzen und die Daten in das Array übertragen.
Stattdessen (wodurch eine andere Array-Referenz festgelegt wird, von
data
der Ihre Benutzeroberfläche nichts weiß):Versuche dies:
Hier ist eine Geige , die den Unterschied zwischen dem Festlegen eines neuen Arrays und dem Leeren und Hinzufügen zu einem vorhandenen Array zeigt. Ich konnte dein plnkr nicht zum Laufen bringen, aber hoffentlich funktioniert das für dich!
quelle
angular.copy(d, data)
wird auch funktionieren. Wenn ein Ziel an die copy () -Methode übergeben wird, werden zuerst die Elemente des Ziels gelöscht und dann die neuen Elemente aus der Quelle kopiert.Im Zusammenhang damit habe ich ein ähnliches Problem durchlaufen, jedoch nicht mit get oder post von Angular, sondern mit einer Erweiterung von einem Drittanbieter (in meinem Fall Chrome Extension).
Das Problem, mit dem ich konfrontiert war, ist, dass die Chrome-Erweiterung nicht zurückgegeben
then()
wird. Daher konnte ich dies nicht wie in der obigen Lösung tun, aber das Ergebnis ist immer noch asynchron.Meine Lösung besteht also darin, einen Dienst zu erstellen und zu einem Rückruf überzugehen
Dann in meinem Controller
Hoffe, dies kann anderen helfen, das gleiche Problem zu bekommen.
quelle
Ich habe http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ gelesen. [AngularJS ermöglicht es uns, unsere Controller-Logik zu optimieren, indem wir ein Versprechen direkt auf den Bereich legen, anstatt das Gelöste manuell zu übergeben Wert in einem erfolgreichen Rückruf.]
so einfach und praktisch :)
Ich hoffe das hilft
quelle
defrred.promise
ist keine Funktion.$scope.items = Data.getData();
ist in Anglular veraltetIch mag die Tatsache wirklich nicht, dass der Verbraucher des Dienstes, der $ http verwendet, aufgrund der "vielversprechenden" Vorgehensweise "wissen" muss, wie die Antwort entpackt werden soll.
Ich möchte nur etwas anrufen und die Daten herausholen, ähnlich wie bei der alten
$scope.items = Data.getData();
Methode, die jetzt veraltet ist .Ich habe es eine Weile versucht und keine perfekte Lösung gefunden, aber hier ist mein bester Schuss ( Plunker ). Es kann für jemanden nützlich sein.
Dann Controller:
Mängel, die ich bereits erkennen kann, sind
getData
kann denobj
Parameter nur in Form eines Objekts akzeptieren (obwohl er auch ein Array akzeptieren könnte), was für viele Anwendungen kein Problem darstellt, aber eine schmerzhafte Einschränkung darstellt$scope.data
mit= {}
ihm ein Objekt ( im Wesentlichen , was zu machen$scope.clearData()
oben der Fall ist), oder= []
für ein Array, oder es wird nicht funktionieren (wir haben schon etwas zu übernehmen , welche Daten kommt). Ich habe versucht, diesen Vorbereitungsschritt IN durchzuführengetData
, aber kein Glück.Nichtsdestotrotz bietet es ein Muster, das das Controller-Boilerplate "Versprechen auspacken" entfernt und in Fällen nützlich sein kann, in denen Sie bestimmte Daten aus $ http an mehr als einer Stelle verwenden möchten, während Sie es trocken halten.
quelle
Was das Zwischenspeichern der Antwort im Dienst betrifft, ist hier eine andere Version, die direkter zu sein scheint als das, was ich bisher gesehen habe:
Dieser Dienst gibt entweder die zwischengespeicherten Daten zurück oder
$http.get
;quelle
Bitte versuchen Sie den folgenden Code
quelle