Je comprends qu'en général, on attache simplement du code de continuation avec un then()
comportement d'appel et de chaîne lors de l'utilisation de promesses.
Cependant, je veux lancer un appel asynchrone enveloppé de promesse, puis lancer séparément un 3 secondes $timeout()
afin de pouvoir effectuer une action de l'interface utilisateur, UNIQUEMENT SI la promesse d'origine n'est pas encore terminée. (Je prévois que cela ne se produirait que sur les connexions lentes, les appareils mobiles en 3G, etc.)
Étant donné une promesse, puis-je vérifier si elle est complète ou non sans blocage ou attente?
Réponses:
Je suppose que cela a été ajouté dans une version récente d'Angular mais il semble y avoir 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, cela n'est pas recommandé car cela pourrait casser lors de la mise à niveau de votre version Angular.
la source
$$...
propriétés ne doivent pas être utilisées. Peut être risqué lors de la mise à niveau vers des versions plus récentes d'Angular ...inspect
fonction. Donc pas de jus pour nous les développeurs angulaires. Promise prototype ne l'a tout simplement pas.Je pense que votre meilleure option telle quelle (sans modifier la source angulaire et soumettre une demande de tirage) est de conserver 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 terminée dans le
then()
pour la promesse d'origine. Dans le$timeout
then()
cochez le drapeau pour savoir si la promesse originale est encore résolue ou non.Quelque chose comme ça:
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
$q
ne les inclut malheureusement pas.la source
Cela ne semble pas possible, comme @shaunhusain l'a déjà mentionné. Mais peut-être que ce n'est 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);
la source
J'ai eu un problème similaire où je dois vérifier si une promesse est revenue. Étant donné que la
$watch
fonction d'AngularJS enregistrera un changement lors du rendu de la page même si les valeurs nouvelles et anciennes ne sont pas définies, je dois vérifier s'il existe des données qui valent la peine d'être stockées dans mon modèle externe.C'est définitivement un hack mais je fais ceci:
$scope.$watch('userSelection', function() { if(promiseObject.hasOwnProperty("$$v"){ userExportableState.selection = $scope.userSelection; } };
Je sais que
$$v
c'est une variable interne utilisée par AngularJS, mais cela a été assez fiable comme 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$q
dans la documentation 1.2, mais peut-être que quelqu'un écrira un service de remplacement avec une meilleure fonctionnalité définie plus près de Q.la source
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).
Si l'
setTimeout()
instruction se trouve dans le même thread d'événement que l'appel asynchrone, vous n'avez pas à vous soucier de la possibilité d'un effet de course. Comme javascript est strictement à thread unique, les.then()
rappels de la promesse sont garantis de se déclencher dans un thread d'événement ultérieur.la source