¿Cuál es la diferencia entre $ evalAsync y $ timeout en AngularJS?

He estado usando AngularJS por un tiempo, y he encontrado la necesidad de usar $ timeout de vez en cuando (parece ser que generalmente se debe iniciar un plugin de jQuery).

Recientemente, he estado tratando de obtener una comprensión mejor y más profunda del ciclo de resumen, y me encontré con la función $ evalAsync .

Parece que esa función produce resultados similares a $timeout , solo que no le da tiempo. Cada vez que uso $timeout ha sido con un retraso de 0, así que ahora me pregunto si debería haber usado $evalAsync en $evalAsync lugar.

¿Hay alguna diferencia fundamental entre los dos? ¿Qué casos usarías uno sobre el otro? Me gustaría tener una mejor idea de cuándo usar cuál.

Recientemente respondí esencialmente esta pregunta aquí: https://stackoverflow.com/a/17239084/215945 (Esa respuesta enlaza con algunos intercambios de Github con Misko).

Para resumir:

  • si el código se pone en cola utilizando $ evalAsync de una directiva , debe ejecutarse después de que Angular manipule el DOM, pero antes de que el navegador lo renderice
  • si el código está en cola usando $ evalAsync desde un controlador , debe ejecutarse antes de que Angular manipule el DOM (y antes de que el navegador lo renderice); rara vez quiere esto.
  • si el código está en cola usando $ timeout , debería ejecutarse después de que Angular haya manipulado el DOM y después de que el navegador lo renderice (lo que puede causar parpadeo en algunos casos)

Para aquellos que crean aplicaciones complejas, tenga en cuenta que hay un impacto en el rendimiento de su elección. Además, me gustaría completar la respuesta de Mark con más detalles técnicos:

  • $ timeout (callback) esperará a que se complete el ciclo de resumen actual (es decir, actualizará todos los modelos y el DOM), luego ejecutará su callback, lo que podría afectar al modelo angular, y luego lanzará $apply completo en el scope $ raíz. y repasar todo.

  • $ evalAsync (callback) , por otro lado, agregará la callback al ciclo de resumen actual o siguiente. Lo que significa que si está dentro de un ciclo de resumen (por ejemplo, en una función llamada desde alguna directiva ng-click ), esto no esperará nada, el código se ejecutará de inmediato. Si se encuentra dentro de una llamada asíncrona, por ejemplo un setTimeout , se setTimeout un nuevo ciclo de resumen ( $apply ).

Por lo tanto, en términos de rendimiento, siempre es mejor llamar a $evalAsync , a menos que sea importante para usted que la vista esté actualizada antes de ejecutar el código, por ejemplo, si necesita acceder a algún atributo DOm como ancho de elementos y similares.

Si desea obtener más detalles sobre la distinción entre $ timeout, $ evalAsync, $ digest, $ apply, lo invito a leer mi respuesta sobre esa otra pregunta: https://stackoverflow.com/a/23102223/1501926

También asegúrese de leer la documentación :

$ EvalAsync no garantiza cuándo se ejecutará la expresión, solo eso:

  • se ejecutará después de la función que programó la evaluación (preferiblemente antes del renderizado DOM).
  • al menos un ciclo $ digest se realizará después de la ejecución de la expresión.

Nota: si se llama a esta función fuera de un ciclo $ digest, se progtwigrá un nuevo ciclo $ digest . Sin embargo, se recomienda llamar siempre al código que cambia el modelo desde una llamada $ apply. Eso incluye el código evaluado a través de $ evalAsync.