Ich versuche, eine Funktion zu schreiben, die ein Versprechen zurückgibt. Es gibt jedoch Situationen, in denen die angeforderten Informationen sofort verfügbar sind. Ich möchte es in ein Versprechen einwickeln, damit der Verbraucher keine Entscheidung treffen muss.
function getSomething(id) {
if (Cache[id]) {
var deferred = $q.defer();
deferred.resolve(Cache[id]); // <-- Can I do this?
return deferred.promise;
} else {
return $http.get('/someUrl', {id:id});
}
}
Und benutze es so:
somethingService.getSomething(5).then(function(thing) {
alert(thing);
});
Das Problem ist, dass der Rückruf für das vorab aufgelöste Versprechen nicht ausgeführt wird. Ist das eine legitime Sache? Gibt es eine bessere Möglichkeit, mit dieser Situation umzugehen?
Kurze Antwort: Ja, Sie können ein AngularJS-Versprechen lösen, bevor Sie es zurückgeben, und es verhält sich wie erwartet.
Von JB Nizets Plunkr aber überarbeitet, um im Kontext dessen zu arbeiten, was ursprünglich verlangt wurde (d. H. Ein Funktionsaufruf zum Service) und tatsächlich vor Ort.
Im Service ...
function getSomething(id) {
// There will always be a promise so always declare it.
var deferred = $q.defer();
if (Cache[id]) {
// Resolve the deferred $q object before returning the promise
deferred.resolve(Cache[id]);
return deferred.promise;
}
// else- not in cache
$http.get('/someUrl', {id:id}).success(function(data){
// Store your data or what ever....
// Then resolve
deferred.resolve(data);
}).error(function(data, status, headers, config) {
deferred.reject("Error: request returned status " + status);
});
return deferred.promise;
}
In der Steuerung ....
somethingService.getSomething(5).then(
function(thing) { // On success
alert(thing);
},
function(message) { // On failure
alert(message);
}
);
Ich hoffe es hilft jemandem. Ich fand die anderen Antworten nicht sehr klar.
Gelöstes Versprechen:
return $q.when( someValue ); // angular 1.2+
return $q.resolve( someValue ); // angular 1.4+, alias to `when` to match ES6
Abgelehntes Versprechen:
return $q.reject( someValue );
Hier ist, wie ich es normalerweise mache, wenn ich tatsächlich Daten in einem Array oder Objekt zwischenspeichern möchte
app.factory('DataService', function($q, $http) {
var cache = {};
var service= {
getData: function(id, callback) {
var deffered = $q.defer();
if (cache[id]) {
deffered.resolve(cache[id])
} else {
$http.get('data.json').then(function(res) {
cache[id] = res.data;
deffered.resolve(cache[id])
})
}
return deffered.promise.then(callback)
}
}
return service
})
Ich benutze gerne eine Fabrik, um die Daten von meiner Ressource zu erhalten.
.factory("SweetFactory", [ "$http", "$q", "$resource", function( $http, $q, $resource ) {
return $resource("/sweet/app", {}, {
"put": {
method: "PUT",
isArray: false
},"get": {
method: "GET",
isArray: false
}
});
}]);
Dann stellen Sie mein Modell hier im Service wie folgt aus
.service("SweetService", [ "$q", "$filter", "$log", "SweetFactory",
function ($q, $filter, $log, SweetFactory) {
var service = this;
//Object that may be exposed by a controller if desired update using get and put methods provided
service.stuff={
//all kinds of stuff
};
service.listOfStuff = [
{value:"", text:"Please Select"},
{value:"stuff", text:"stuff"}];
service.getStuff = function () {
var deferred = $q.defer();
var promise = SweetFactory.get().$promise.then(
function (response) {
if (response.response.result.code !== "COOL_BABY") {
deferred.reject(response);
} else {
deferred.resolve(response);
console.log("stuff is got", service.alerts);
return deferred.promise;
}
}
).catch(
function (error) {
deferred.reject(error);
console.log("failed to get stuff");
}
);
promise.then(function(response){
//...do some stuff to sett your stuff maybe fancy it up
service.stuff.formattedStuff = $filter('stuffFormatter')(service.stuff);
});
return service.stuff;
};
service.putStuff = function () {
console.log("putting stuff eh", service.stuff);
//maybe do stuff to your stuff
AlertsFactory.put(service.stuff).$promise.then(function (response) {
console.log("yep yep", response.response.code);
service.getStuff();
}).catch(function (errorData) {
alert("Failed to update stuff" + errorData.response.code);
});
};
}]);
Dann können meine Controller es einbinden und es offenlegen oder tun, was es in seinem Kontext für richtig hält, indem sie einfach auf den injizierten Service verweisen
Scheint ok zu funktionieren. Aber ich bin ein bisschen neu in eckigen. * Fehlerbehandlung meist aus Gründen der Übersichtlichkeit weggelassen
Sie haben vergessen, das Cache-Element zu initialisieren
function getSomething(id) {
if (Cache[id]) {
var deferred = $q.defer();
deferred.resolve(Cache[id]); // <-- Can I do this?
return deferred.promise;
} else {
Cache[id] = $http.get('/someUrl', {id:id});
return Cache[id];
}
}