props name emberjs ember create component classnamebindings bubbling ember.js

ember.js - name - ¿Qué es Ember RunLoop y cómo funciona?



ember on hover (1)

Actualización 10/9/2013: consulte esta visualización interactiva del ciclo de ejecución: https://machty.s3.amazonaws.com/ember-run-loop-visual/index.html

Actualización 5/9/2013: todos los conceptos básicos a continuación todavía están actualizados, pero a partir de este compromiso , la implementación de Ember Run Loop se ha dividido en una biblioteca independiente llamada backburner.js , con algunas diferencias de API muy menores.

Primero, lee esto:

http://blog.sproutcore.com/the-run-loop-part-1/

http://blog.sproutcore.com/the-run-loop-part-2/

No son 100% precisas para Ember, pero los conceptos básicos y la motivación detrás de RunLoop todavía se aplican generalmente a Ember; solo algunos detalles de implementación difieren. Pero, a sus preguntas:

¿Cuándo comienza Ember RunLoop? ¿Depende de enrutador o vistas o controladores o alguna otra cosa?

Todos los eventos básicos del usuario (por ejemplo, eventos de teclado, eventos de mouse, etc.) activarán el ciclo de ejecución. Esto garantiza que cualquier cambio realizado en las propiedades enlazadas por el evento capturado (mouse / keyboard / timer / etc) se propaga por completo en el sistema de enlace de datos de Ember antes de devolver el control al sistema. Por lo tanto, moviendo el mouse, presionando una tecla, haciendo clic en un botón, etc., todos inician el ciclo de ejecución.

¿Cuánto tiempo tarda aproximadamente (sé que esto es bastante tonto para las preguntas y depende de muchas cosas, pero estoy buscando una idea general, o tal vez si hay un tiempo mínimo o máximo que puede tomar un runloop)

En ningún momento RunLoop hará un seguimiento del tiempo que lleva propagar todos los cambios a través del sistema y luego detener el RunLoop después de alcanzar un límite de tiempo máximo; más bien, RunLoop siempre se ejecutará hasta su finalización, y no se detendrá hasta que se hayan invocado todos los temporizadores caducados, se hayan propagado enlaces y tal vez se hayan propagado sus enlaces, y así sucesivamente. Obviamente, cuantos más cambios deban ser propagados desde un solo evento, más tiempo tardará RunLoop en terminar. Este es un ejemplo (bastante injusto) de cómo RunLoop puede atascarse con la propagación de cambios en comparación con otro framework (Backbone) que no tiene un bucle de ejecución: http://jsfiddle.net/jashkenas/CGSd5/ . Moraleja de la historia: el RunLoop es realmente rápido para la mayoría de las cosas que siempre quisieras hacer en Ember, y es donde reside gran parte del poder de Ember, pero si te dan ganas de animar 30 círculos con Javascript a 60 fotogramas por segundo, hay podría ser una mejor manera de hacerlo que confiar en Ember''s RunLoop.

¿RunLoop se está ejecutando en todo momento o solo indica un período de tiempo desde el principio hasta el final de la ejecución y es posible que no se ejecute durante un tiempo.

No se ejecuta en todo momento: tiene que devolver el control al sistema en algún momento o de lo contrario la aplicación se bloquea. Es diferente de, por ejemplo, un ciclo de ejecución en un servidor que tiene un while(true) y se va encendido para infinito hasta que el servidor recibe una señal para apagarse ... el Ember RunLoop no tiene tal while(true) pero solo se activa en respuesta a los eventos de usuario / temporizador.

Si se crea una vista desde dentro de un RunLoop, ¿se garantiza que todo su contenido llegará al DOM en el momento en que termine el ciclo?

Veamos si podemos darnos cuenta de eso. Uno de los grandes cambios de SC a Ember RunLoop es que, en lugar de ir y venir entre invokeOnce y invokeLast (que se ve en el diagrama del primer enlace sobre SproutCore''s RL), Ember te proporciona una lista de ''colas'' que, en el transcurso de un ciclo de ejecución, puede programar acciones (funciones a las que se llamará durante el ciclo de ejecución) especificando a qué cola pertenece la acción (ejemplo de la fuente: Ember.run.scheduleOnce(''render'', bindView, ''rerender''); ).

Si run_loop.js en el código fuente, ves Ember.run.queues = [''sync'', ''actions'', ''destroy'', ''timers'']; , sin embargo, si abre su depurador JavaScript en el navegador en una aplicación Ember y evalúa Ember.run.queues , obtendrá una lista más completa de colas: ["sync", "actions", "render", "afterRender", "destroy", "timers"] . Ember mantiene su base de código bastante modular, y hacen posible que su código, así como su propio código en una parte separada de la biblioteca, inserte más colas. En este caso, la biblioteca Ember Views inserta las colas render y afterRender , específicamente después de la cola de actions . Voy a llegar a por qué eso podría ser en un segundo. Primero, el algoritmo RunLoop:

El algoritmo RunLoop es prácticamente el mismo que se describe en los artículos de ciclo de ejecución SC anteriores:

  • Ejecuta su código entre RunLoop .begin() y .end() , solo en Ember querrá ejecutar su código dentro de Ember.run , que internamente llamará a begin y end para usted. (Solo el código interno de bucle de ejecución en la base de código Ember aún usa begin y end , por lo que debe seguir con Ember.run )
  • Después de llamar a end() , RunLoop se pone en marcha para propagar cada cambio realizado por el fragmento de código pasado a la función Ember.run . Esto incluye la propagación de los valores de las propiedades enlazadas, la representación de los cambios en el DOM, etc. El orden en el que se realizan estas acciones (vinculante, representación de los elementos DOM, etc.) está determinado por la matriz Ember.run.queues descrita anteriormente:
  • El ciclo de ejecución comenzará en la primera cola, que es sync . Ejecutará todas las acciones que se programaron en la cola de sync mediante el código Ember.run . Estas acciones también pueden programar más acciones durante este mismo RunLoop, y depende de RunLoop para asegurarse de que realiza cada acción hasta que todas las colas se vacían. La forma en que lo hace es que, al final de cada cola, RunLoop buscará en todas las colas lavadas anteriormente y verá si se han programado nuevas acciones. Si es así, debe comenzar al principio de la cola más temprana con acciones programadas no ejecutadas y eliminar la cola, seguir sus pasos y volver a comenzar cuando sea necesario hasta que todas las colas estén completamente vacías.

Esa es la esencia del algoritmo. Así es como los datos vinculados se propagan a través de la aplicación. Puede esperar que una vez que RunLoop se ejecute hasta su finalización, todos los datos enlazados se propagarán por completo. Entonces, ¿qué pasa con los elementos DOM?

El orden de las colas, incluidas las agregadas por la biblioteca Ember Views, es importante aquí. Observe que render y afterRender aparecen después de la sync y la action . La cola de sync contiene todas las acciones para propagar datos encuadernados. (La action , después de eso, solo se usa escasamente en la fuente Ember). Basado en el algoritmo anterior, se garantiza que para cuando RunLoop llegue a la cola de render , todos los enlaces de datos habrán terminado de sincronizarse. Esto es por diseño: no querría realizar la costosa tarea de renderizar elementos DOM antes de sincronizar los enlaces de datos, ya que eso requeriría volver a renderizar elementos DOM con datos actualizados, obviamente un error muy ineficiente y modo propenso de vaciar todas las colas de RunLoop. Así que Ember acelera de manera inteligente todo el trabajo de enlace de datos que pueda antes de representar los elementos DOM en la cola de render .

Por lo tanto, para responder a su pregunta, sí, puede esperar que todas las representaciones de DOM necesarias se hayan realizado cuando termine Ember.run . Aquí hay un jsFiddle para demostrar: http://jsfiddle.net/machty/6p6XJ/328/

Otras cosas que debe saber sobre el RunLoop

Observadores vs. enlaces

Es importante tener en cuenta que los Observadores y Vinculaciones, aunque tienen la funcionalidad similar de responder a los cambios en una propiedad "vista", se comportan de manera totalmente diferente en el contexto de un RunLoop. La propagación de enlace, como hemos visto, se programa en la cola de sync para eventualmente ser ejecutada por RunLoop. Los observadores, por otro lado, disparan inmediatamente cuando la propiedad vigilada cambia sin tener que programarse primero en una cola RunLoop. Si un observador y un enlace "miran" la misma propiedad, el observador siempre será llamado el 100% del tiempo antes de que se actualice el enlace.

scheduleOnce y Ember.run.once

Uno de los grandes aumentos de eficiencia en las plantillas de actualización automática de Ember se basa en el hecho de que, gracias a RunLoop, múltiples acciones RunLoop idénticas pueden combinarse ("desprestigiarse", si se quiere) en una sola acción. Si observa las run_loop.js internas de run_loop.js , verá que las funciones que facilitan este comportamiento son las funciones relacionadas scheduleOnce y Em.run.once . La diferencia entre ellos no es tan importante como saber que existen, y cómo pueden descartar acciones duplicadas en cola para evitar una gran cantidad de cálculos inflados y derrochadores durante el ciclo de ejecución.

¿Qué hay de los temporizadores?

Aunque ''temporizadores'' es una de las colas predeterminadas enumeradas anteriormente, Ember solo hace referencia a la cola en sus casos de prueba de RunLoop. Parece que dicha cola se habría utilizado en los días de SproutCore en función de algunas de las descripciones de los artículos anteriores sobre temporizadores que son lo último que se dispara. En Ember, la cola de timers no se usa. En cambio, RunLoop puede ser spun up por un evento setTimeout gestionado setTimeout (ver la función invokeLaterTimers ), que es lo suficientemente inteligente como para recorrer todos los temporizadores existentes, activar todos los que hayan expirado, determinar el temporizador futuro más temprano y establecer un setTimeout interno setTimeout para ese evento, que activará nuevamente RunLoop cuando se active. Este enfoque es más eficiente que tener cada llamada de temporizador setTimeout y reactivarse, ya que en este caso, solo se necesita hacer una llamada de setTimeout, y RunLoop es lo suficientemente inteligente como para disparar todos los diferentes temporizadores que puedan estar sonando al mismo tiempo. hora.

Eliminación de rebotes con la cola de sync

Aquí hay un fragmento del ciclo de ejecución, en el medio de un ciclo a través de todas las colas en el ciclo de ejecución. Tenga en cuenta el caso especial de la cola de sync : como la sync es una cola particularmente volátil, en la que los datos se propagan en todas las direcciones, se llama a Ember.beginPropertyChanges() para evitar el disparo de observadores, seguido de una llamada a Ember.endPropertyChanges . Esto es sabio: si en el curso de la descarga de la cola de sync , es completamente posible que una propiedad en un objeto cambie varias veces antes de descansar en su valor final, y no querrá perder recursos disparando inmediatamente observadores por cada simple cambio.

if (queueName === ''sync'') { log = Ember.LOG_BINDINGS; if (log) { Ember.Logger.log(''Begin: Flush Sync Queue''); } Ember.beginPropertyChanges(); Ember.tryFinally(tryable, Ember.endPropertyChanges); if (log) { Ember.Logger.log(''End: Flush Sync Queue''); } } else { forEach.call(queue, iter); }

Espero que esto ayude. Definitivamente tuve que aprender bastante solo para escribir esto, lo cual fue un punto.

Estoy tratando de entender cómo funciona Ember RunLoop y qué lo hace funcionar. He revisado la documentación , pero todavía tengo muchas preguntas al respecto. Estoy interesado en comprender mejor cómo funciona RunLoop para poder elegir el método apropiado dentro de su espacio de nombre, cuando tengo que diferir la ejecución de algún código para más adelante.

  • ¿Cuándo comienza Ember RunLoop? ¿Depende de enrutador o vistas o controladores o alguna otra cosa?
  • ¿Cuánto tiempo tarda aproximadamente (sé que esto es bastante tonto para las preguntas y depende de muchas cosas, pero estoy buscando una idea general, o tal vez si hay un tiempo mínimo o máximo que puede tomar un runloop)
  • ¿RunLoop se está ejecutando en todo momento o solo indica un período de tiempo desde el principio hasta el final de la ejecución y es posible que no se ejecute durante un tiempo.
  • Si se crea una vista desde dentro de un RunLoop, ¿se garantiza que todo su contenido llegará al DOM en el momento en que termine el ciclo?

Perdónenme si estas son preguntas muy básicas, creo que entender esto ayudará a noobs como yo a usar Ember mejor.