181 votes

Quelle est la différence entre $evalAsync et $timeout dans AngularJS ?

J'utilise AngularJS depuis un petit moment maintenant, et j'ai trouvé le besoin d'utiliser $timeout de temps en temps (il semble que ce soit généralement pour lancer un plugin jQuery).

Récemment, j'ai essayé de mieux comprendre le cycle de digestion, et je suis tombée sur $evalAsync fonction.

Il semble que cette fonction produise des résultats similaires à ceux de $timeout mais vous ne lui donnez pas de délai. Chaque fois que j'ai utilisé $timeout il l'a été avec un délai de 0. Je me demande donc si je n'aurais pas dû utiliser $evalAsync au lieu de cela.

Existe-t-il des différences fondamentales entre les deux ? Dans quels cas utiliseriez-vous l'un plutôt que l'autre ? J'aimerais avoir une meilleure idée du moment où il faut utiliser l'un ou l'autre.

267voto

Mark Rajcok Points 85912

J'ai récemment répondu à cette question ici : https://stackoverflow.com/a/17239084/215945 (Cette réponse renvoie à des échanges avec Misko sur github).

En résumé :

  • si le code est mis en file d'attente à l'aide de $evalAsync à partir d'une directive il devrait fonctionner après le DOM a été manipulé par Angular, mais antes de le navigateur rend
  • si le code est mis en file d'attente à l'aide de $evalAsync depuis un contrôleur il devrait fonctionner antes de le DOM a été manipulé par Angular (et avant que le navigateur ne rende) -- il est rare que vous souhaitiez cela
  • si le code est mis en file d'attente à l'aide de $timeout il devrait fonctionner après le DOM a été manipulé par Angular, et après le rendu par le navigateur (ce qui peut provoquer un scintillement dans certains cas)

15 votes

Merci pour cette explication. Il y a cependant une chose que je ne suis pas sûr de comprendre. Pourquoi cela fait-il une différence si vous appelez $evalAsync à partir d'un contrôleur ou d'une directive ? L'asyncQueue ne sait pas s'il a été enregistré à partir d'un contrôleur ou d'une directive, il se contente de le mettre en file d'attente dans le champ d'application actuel. Est-ce que cela a un rapport avec le moment où les choses s'exécutent dans un contrôleur par rapport à un contrôleur ? Je veux juste comprendre cette partie.

0 votes

@dnc253, je n'ai pas regardé le code Angular, donc je ne connais pas la réponse à votre (bonne) question. J'espère que quelqu'un d'autre pourra vous répondre.

15 votes

L'expression "à partir d'une directive" signifie-t-elle "à partir de la fonction de liaison d'une directive" ? Ou cela vaut-il pour le comportement lorsqu'il est exécuté à partir de la méthode de lien ou de contrôleur d'une directive ?

59voto

floribon Points 1149

Pour ceux qui construisent des applications complexes, sachez que votre choix aura un impact sur les performances. Par ailleurs, j'aimerais compléter la réponse de Mark par des détails techniques :

  • $timeout(callback) attendra que le cycle de digestion en cours soit terminé (c.-à-d. qu'angular mette à jour tous les modèles et le DOM), puis il exécutera son callback - affectant potentiellement le modèle angulaire - et lancera un cycle complet de $apply sur la racine $scope, et redigérer le tout.

  • $evalAsync(callback) en revanche, ajoutera le rappel au cycle de digestion en cours ou suivant. Ce qui signifie que si vous êtes dans un cycle de digestion (par exemple dans une fonction appelée à partir d'une fonction ng-click ), cela n'attendra rien, le code sera exécuté immédiatement. Si vous êtes dans un appel asynchrone, par exemple une commande setTimeout , un nouveau cycle de digestion ( $apply ) sera déclenché.

En termes de performances, il est donc toujours préférable d'appeler $evalAsync La vue doit être mise à jour avant l'exécution du code, sauf s'il est important pour vous que la vue soit à jour avant d'exécuter votre code, par exemple si vous avez besoin d'accéder à un attribut DOm tel que la largeur de l'élément ou d'autres éléments similaires.

Si vous voulez plus de détails sur la distinction entre $timeout, $evalAsync, $digest, $apply, je vous invite à lire ma réponse à cette autre question : https://stackoverflow.com/a/23102223/1501926

Veillez également à lire le la documentation :

L'option $evalAsync ne garantit pas le moment où l'expression sera exécutée, mais seulement qu'elle le sera :

  • elle s'exécutera après la fonction qui a programmé l'évaluation (de préférence avant le rendu du DOM).
  • au moins un cycle $digest sera effectué après l'exécution de l'expression.

Remarque : si cette fonction est appelée en dehors d'un cycle $digest, un nouveau cycle $digest sera programmé . Cependant, il est recommandé de toujours appeler le code qui modifie le modèle à partir d'un appel à $apply. Cela inclut le code évalué via $evalAsync.

1voto

Vijey Points 769

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