J'essaie d'écrire une fonction qui retourne une promesse. Mais il y a des moments où les informations demandées sont disponibles immédiatement. Je veux l'envelopper dans une promesse afin que le consommateur n'ait pas à prendre de décision.
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});
}
}
Et utilisez-le comme ceci:
somethingService.getSomething(5).then(function(thing) {
alert(thing);
});
Le problème est que le rappel ne s'exécute pas pour la promesse pré-résolue. Est-ce une chose légitime à faire? Y a-t-il une meilleure façon de gérer cette situation?
Réponse courte: Oui, vous pouvez résoudre une promesse AngularJS avant de la retourner, et elle se comportera comme prévu.
À partir de Plunkr de JB Nizet mais refactorisé pour fonctionner dans le contexte de ce qui avait été demandé à l'origine (c'est-à-dire un appel de fonction au service) et réellement sur site.
Dans le 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;
}
À l'intérieur du contrôleur ....
somethingService.getSomething(5).then(
function(thing) { // On success
alert(thing);
},
function(message) { // On failure
alert(message);
}
);
J'espère que ça aide quelqu'un. Je n'ai pas trouvé les autres réponses très claires.
Promesse résolue:
return $q.when( someValue ); // angular 1.2+
return $q.resolve( someValue ); // angular 1.4+, alias to `when` to match ES6
Promesse rejetée:
return $q.reject( someValue );
Voici comment je le fais généralement si je veux réellement mettre en cache des données dans un tableau ou un objet
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
})
J'aime utiliser une usine pour obtenir les données de ma ressource quelque chose comme.
.factory("SweetFactory", [ "$http", "$q", "$resource", function( $http, $q, $resource ) {
return $resource("/sweet/app", {}, {
"put": {
method: "PUT",
isArray: false
},"get": {
method: "GET",
isArray: false
}
});
}]);
Puis exposer mon modèle dans le service comme celui-ci ici
.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);
});
};
}]);
Ensuite, mes contrôleurs peuvent l'inclure et l'exposer ou faire ce qu'il trouve correct dans son contexte simplement en référençant le Service injecté.
Semble travailler ok. Mais je suis un peu nouveau à angular. * le traitement des erreurs est généralement laissé de côté pour plus de clarté
Vous avez oublié d'initialiser l'élément Cache
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];
}
}