85 votes

Comment vérifier si une promesse angulaire $q est résolue ?

Je comprends qu'en règle générale, il suffit d'attacher le code de continuation à un fichier then() le comportement des appels et des chaînes lors de l'utilisation de promesses.

Cependant, je veux lancer un appel asynchrone enveloppé d'une promesse, puis lancer séparément un appel asynchrone de 3 secondes. $timeout() afin que je puisse prendre une mesure d'assurance-chômage, UNIQUEMENT SI la promesse initiale n'a pas encore été tenue. (Je pense que cela ne se produira que sur des connexions lentes, des appareils mobiles en 3G, etc.)

Étant donné une promesse, puis-je vérifier si elle est complète ou non sans bloquer ou attendre ?

46voto

parliament Points 1816

Je suppose que cela a été ajouté dans une version récente d'Angular mais il semble qu'il y ait maintenant un objet $$state sur la promesse :

 var deferred = $q.defer();
 console.log(deferred.promise.$$state.status); // 0
 deferred.resolve();
 console.log(deferred.promise.$$state.status); //1 

Comme indiqué dans les commentaires, ce n'est pas recommandé car cela pourrait se casser lors de la mise à jour de votre version d'Angular.

36voto

shaunhusain Points 10933

Je pense que votre meilleure option en l'état (sans modifier les sources d'Angular et soumettre une pull request) est de garder un drapeau local pour savoir si la promesse a été résolue. Réinitialisez-le à chaque fois que vous configurez la promesse qui vous intéresse et marquez-la comme complète dans le fichier then() pour la promesse initiale. Dans le cadre de la $timeout then() vérifier le drapeau pour savoir si la promesse originale a été résolue ou non.

Voici ce qu'il en est :

var promiseCompleted = false;
promise.then(function(){promiseCompleted=true;})
$timeout(...).then(function(){if(!promiseCompleted)doStuff()})

L'implémentation de Kris Kowal inclut d'autres méthodes pour vérifier l'état de la promesse, mais il semble que l'implémentation d'Angular de la méthode $q ne les inclut malheureusement pas.

8voto

Bergi Points 104242

Cela ne semble pas possible, comme l'a déjà mentionné @shaunhusain. Mais ce n'est peut-être pas nécessaire :

// shows stuff from 3s ahead to promise completetion, 
// or does and undoes it in one step if promise completes before
$q.all(promise, $timeout(doStuff, 3000)).then(undoStuff);

ou peut-être mieux :

var tooSlow = $timeout(doStuff, 3000);
promise.always(tooSlow.cancel);

1voto

PatchCR Points 33

J'ai eu un problème similaire où j'ai besoin de vérifier si une promesse a été retournée. Parce que la fonction $watch enregistrera un changement lors du rendu de la page même si la nouvelle et l'ancienne valeur sont indéfinies, je dois vérifier si des données méritent d'être stockées dans mon modèle externe.

Il s'agit d'un véritable piratage, mais c'est ce que je fais :

$scope.$watch('userSelection', function() {
  if(promiseObject.hasOwnProperty("$$v"){
    userExportableState.selection = $scope.userSelection;
  }
};

Je sais que $$v est une variable interne utilisée par AngularJS, mais elle s'est avérée assez fiable en tant qu'indicateur d'une promesse résolue pour nous. Qui sait ce qui se passera lorsque nous passerons à AngularJS 1.2 :-/ Je ne vois aucune mention d'améliorations pour $q dans la documentation de la version 1.2, mais peut-être que quelqu'un écrira un service de remplacement avec un ensemble de fonctionnalités plus proche de Q.

0voto

Beetroot-Beetroot Points 12006

Je ne connais pas votre scénario exact, mais il est plus courant de mettre en place un délai d'attente immédiatement après avoir effectué l'appel asynchrone (et généré la promesse).

Fournir le setTimeout() se trouve dans le même fil d'événements que l'appel asynchrone, vous n'avez pas à vous soucier de la possibilité d'un effet de course. Comme le javascript est strictement monofilaire, l'appel asynchrone de la promesse .then() sont garantis de se déclencher dans un thread d'événement ultérieur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X