Qu'est-ce que la Braise RunLoop et comment ça fonctionne?
Je suis en train d'essayer de comprendre comment Braise RunLoop qui fonctionne et ce qui la fait marcher. J'ai regardé la documentation, mais encore beaucoup de questions à ce sujet. Je suis intéressé à mieux comprendre le RunLoop œuvres, afin de pouvoir choisir la méthode la plus appropriée à l'intérieur de son espace de nom, quand j'ai de reporter l'exécution d'un code pour plus tard.
- Quand Braise RunLoop commencer. Est-il dépend de Routeur ou de points de Vue ou des Contrôleurs ou autre chose?
- combien de temps faut-il environ (je sais c'est plutôt idiot de la demande et dépend de beaucoup de choses, mais je suis à la recherche d'une idée générale, ou peut-être si il est un minimum ou un maximum de temps un runloop peut prendre)
- Est RunLoop être exécuté à tout moment, ou est-ce juste indiquant une période de temps à partir de début à la fin de l'exécution et peut ne pas fonctionner pendant un certain temps.
- Si une vue est créée à partir d'un RunLoop, est-il garanti que l'ensemble de son contenu fera dans les DOM, le temps que la boucle se termine?
Pardonnez-moi si ce sont des questions très de base, je pense que la compréhension de ces va aider les noobs comme moi utiliser Braise mieux.
- Il n'y a pas grand docs sur l'exécution de la boucle. Je vais essayer de mettre sur pied une série de diapositives sur cette semaine.
- ce serait génial @Luc. C'est l'un des dur coins de Braise qui est moins reconnu. Hâte d'y être!
- cette question a désespérément besoin de votre attention et il semble que d'autres personnes sont à la recherche pour la même information. Ce serait merveilleux, si vous en avez l'occasion, à partager vos idées sur RunLoop.
Vous devez vous connecter pour publier un commentaire.
Mise à jour 10/9/2013: découvrez cette visualisation interactive de l'exécution de la boucle: https://machty.s3.amazonaws.com/ember-run-loop-visual/index.html
Mise à jour 5/9/2013: tous les concepts de base ci-dessous sont toujours d'actualité, mais aussi de ce commit, la Braise à l'Exécution de la Boucle de la mise en œuvre a été scindé dans une bibliothèque distincte appelée backburner.js, avec quelques petits API différences.
Tout d'abord, la lecture de ces:
http://blog.sproutcore.com/the-run-loop-part-1/
http://blog.sproutcore.com/the-run-loop-part-2/
Ils ne sont pas précis à 100% de Braise, mais les concepts de base et la motivation derrière la RunLoop toujours s'appliquent généralement à la Braise; seuls quelques détails de mise en œuvre diffèrent. Mais, à vos questions:
Quand Braise RunLoop commencer. Est-il dépend de Routeur ou de points de Vue ou des Contrôleurs ou autre chose?
De base les événements de l'utilisateur (par exemple un clavier, les événements, les événements de souris, etc) sera le feu jusqu'à l'exécution de la boucle. Cela garantit que quelles que soient les modifications apportées aux propriétés liées par la capture (souris/clavier/timer/etc) de l'événement sont entièrement répercutée tout au long de Braise du système de liaison de données avant de rendre le contrôle de retour pour le système. Ainsi, en déplaçant votre souris, en appuyant sur une touche, un bouton, etc., tous de lancer l'exécution de la boucle.
combien de temps faut-il environ (je sais c'est plutôt idiot de la demande et dépend de beaucoup de choses, mais je suis à la recherche d'une idée générale, ou peut-être si il est un minimum ou un maximum de temps un runloop peut prendre)
À aucun point de la RunLoop jamais garder une trace de combien de temps cela prend pour propager toutes les modifications dans le système et puis stopper la RunLoop après avoir atteint un maximum de limite de temps; au contraire, la RunLoop sera toujours exécuté jusqu'à la fin, et ne s'arrêtera pas jusqu'à ce que l'expiration des minuteries ont été appelés, les liaisons propagées, et peut-être leur liaisons multiplié, et ainsi de suite. Évidemment, plus les changements qui doivent être propagées à partir d'un seul événement, le plus de la RunLoop prendra à la fin. Voici une (assez déloyale) exemple de la façon dont la RunLoop peut s'enliser avec la propagation des modifications par rapport à l'autre cadre (colonne vertébrale), qui ne dispose pas d'une course en boucle: http://jsfiddle.net/jashkenas/CGSd5/ . Morale de l'histoire: la RunLoop est vraiment rapide pour la plupart des choses que vous avez envie de faire dans la Braise, et c'est là que beaucoup de Braise de la puissance des mensonges, mais si vous vous trouvez vouloir animer de 30 cercles avec Javascript à 60 images par seconde, il pourrait y avoir de meilleures façons d'aller à ce sujet que de compter sur la Braise du RunLoop.
Est RunLoop être exécuté à tout moment, ou est-ce juste indiquant une période de temps à partir de début à la fin de l'exécution et peut ne pas fonctionner pendant un certain temps.
Il n'est pas exécuté à tout moment, il doit revenir en arrière pour le système à un moment ou un autre de votre application aurait pour effet de bloquer -- c'est différent, disons, une course en boucle sur un serveur qui a un
while(true)
et s'en va à l'infini jusqu'à ce que le serveur reçoit un signal pour arrêter... la Braise RunLoop n'a pas de telswhile(true)
mais n'est lancé en réponse à l'utilisateur/les événements de la minuterie.Si une vue est créée à partir d'un RunLoop, est-il garanti que l'ensemble de son contenu fera dans les DOM, le temps que la boucle se termine?
Nous allons voir si nous pouvons comprendre cela. L'un des grands changements de SC de Braise RunLoop est que, au lieu de boucle de retour et vient entre
invokeOnce
etinvokeLast
(que vous voyez dans le diagramme dans le premier lien sur SproutCore du RL), Ember vous propose une liste des "files d'attente" qui, dans le cadre d'un parcours en boucle, vous pouvez programmer des actions (fonctions d'être appelé au cours de l'exécution de la boucle) pour en spécifiant file d'attente à laquelle appartient l'action (par exemple à partir de la source:Ember.run.scheduleOnce('render', bindView, 'rerender');
).Si vous regardez
run_loop.js
dans le code source, vous voyezEmber.run.queues = ['sync', 'actions', 'destroy', 'timers'];
, mais si vous ouvrez votre débogueur JavaScript dans le navigateur dans une Braise d'application et d'évaluerEmber.run.queues
, vous obtenez une liste plus complète des files d'attente:["sync", "actions", "render", "afterRender", "destroy", "timers"]
. Braise garde de leur code assez modulaire, et ils le rendent possible pour votre code, ainsi que son propre code dans une partie distincte de la bibliothèque, d'insérer plus de files d'attente. Dans ce cas, la Braise Vues de la bibliothèque insèrerender
etafterRender
files d'attente, plus précisément après leactions
file d'attente. Je vais arriver à pourquoi dans une seconde. Tout d'abord, le RunLoop algorithme:La RunLoop algorithme est à peu près la même que celle décrite dans la SC exécuter la boucle articles ci-dessus:
.begin()
et.end()
, seulement dans la Braise, vous aurez envie de lancer à la place de votre code dansEmber.run
, ce qui va à l'interne appelbegin
etend
pour vous. (Uniquement interne à l'exécution de la boucle de code dans la Braise à base de code utilise encorebegin
etend
, de sorte que vous devrait simplement s'en tenir avecEmber.run
)end()
est appelée, le RunLoop puis des coups de pied à la vitesse supérieure pour se propager tout seul changement effectué par le fragment de code passé à laEmber.run
fonction. Cela inclut de propager les valeurs de propriétés liées, le rendu de la vue des changements pour les DOM, etc etc. L'ordre dans lequel ces actions (de liaison, le rendu des éléments du DOM, etc) est déterminé par leEmber.run.queues
tableau décrit ci-dessus:sync
. Il va exécuter toutes les actions qui ont été prévus dans lesync
file d'attente par leEmber.run
code. Ces actions peuvent, elles aussi prévoir d'autres actions à accomplir au cours de cette même RunLoop, et c'est à la RunLoop pour s'assurer qu'il effectue toutes les actions jusqu'à ce que toutes les files d'attente sont vidées. La façon dont il le fait est, à la fin de chaque file d'attente, le RunLoop vais regarder à travers toutes les déjà vidé les files d'attente et de voir si de nouvelles actions ont été programmées. Si oui, il faut commencer dès le début de la première file d'attente avec impayée les actions planifiées et rincer la file d'attente, en continuant à suivre ses étapes et recommencer si nécessaire jusqu'à ce que toutes les files d'attente sont complètement vides.C'est l'essence même de l'algorithme. C'est comment de données lié obtient propagée par le biais de l'application. Vous pouvez vous attendre une fois un RunLoop s'exécute à la fin, toutes les données liées seront entièrement répercutée. Donc, concernant des éléments du DOM?
L'ordre des files d'attente, y compris ceux ajoutés par la Braise de Vue de la bibliothèque, est important ici. Notez que
render
etafterRender
venir aprèssync
, etaction
. Lesync
file d'attente contient toutes les actions pour la multiplication de données liée. (action
, après cela, n'est que faiblement utilisé dans la Braise à la source). Basé sur l'algorithme ci-dessus, il est garanti que par le temps de la RunLoop arrive à larender
file d'attente, toutes les données-les liaisons ont terminé la synchronisation. C'est par la conception: vous ne voulez pas effectuer la tâche chère de rendu des éléments du DOM avant de synchronisation avec les données des fixations, parce que ce serait probablement besoin de re-rendu des éléments du DOM avec des données mises à jour -- évidemment une très inefficace et sujette à erreur façon de vider tous les RunLoop files d'attente. Afin de Braise intelligemment explosions à travers toutes les données de liaison de travail il peut, avant de rendre les éléments du DOM dans lerender
file d'attente.Donc, finalement, pour répondre à votre question, oui, vous pouvez vous attendre que tous les DOM rendus ont eu lieu par le temps
Ember.run
finitions. Voici un jsFiddle à démontrer: http://jsfiddle.net/machty/6p6XJ/328/D'autres choses à savoir sur le RunLoop
Observateurs vs Liaisons
Il est important de noter que les Observateurs et les Liaisons, tout en ayant des fonctionnalités similaires de répondre aux changements dans un "vu" de la propriété, de se comporter d'une façon totalement différente dans le contexte d'une RunLoop. La liaison de la propagation, comme nous l'avons vu, se prévu dans le
sync
file d'attente pour finalement être exécuté par le RunLoop. Les observateurs, d'autre part, le feu immédiatement lorsque l'regardé des modifications de la propriété sans avoir à être en premier lieu dans un RunLoop file d'attente. Si un Observateur de liaison et d'un ensemble de "regarder" la même propriété, l'observateur sera toujours 100% du temps, plus tôt que la liaison sera mis à jour.scheduleOnce
etEmber.run.once
L'un des grands efficacité renforce dans la Braise de l'auto-mise à jour des modèles est basée sur le fait que, grâce à la RunLoop, plusieurs identiques RunLoop actions peuvent être corrigées ("sans rebond, si vous voulez) en une seule action. Si vous regardez dans le
run_loop.js
interne, vous verrez les fonctions qui facilitent ce comportement sont les fonctions liées à lascheduleOnce
etEm.run.once
. La différence entre eux n'est pas aussi important que de savoir qu'ils existent, et comment ils peuvent se débarrasser de dupliquer les actions dans la file d'attente pour éviter beaucoup de ballonnement, de gaspillage de calcul au cours de l'exécution de la boucle.Que sur les minuteurs?
Même si "vieille" est l'une des files d'attente par défaut énumérés ci-dessus, de Braise ne fait référence qu'à la file d'attente dans leur RunLoop cas de test. Il semble qu'une telle file d'attente aurait été utilisé dans le SproutCore jours d'après certaines descriptions de l'au-dessus des articles sur des timers la dernière chose à feu. Dans la Braise, la
timers
file d'attente n'est pas utilisé. Au lieu de cela, le RunLoop peut être lancé par un gérés à l'internesetTimeout
de l'événement (voir lainvokeLaterTimers
fonction), ce qui est assez intelligent pour faire une boucle dans toutes les minuteries, feu de tous ceux qui ont expiré, de déterminer le plus tôt avenir de la minuterie, et de définir un internesetTimeout
pour cet événement, qui va faire tourner le RunLoop de nouveau quand il se déclenche. Cette approche est plus efficace que d'avoir chaque minuterie d'appel setTimeout et le réveil lui-même, puisque dans ce cas, seul un setTimeout appel doit être faite, et la RunLoop est assez intelligent pour tirer toutes les différentes minuteries qui pourrait se passer en même temps.Plus d'anti-rebond avec la
sync
file d'attenteVoici un extrait de l'exécution de la boucle, au milieu d'une boucle sur toutes les files d'attente de l'exécution de la boucle. Noter le cas particulier de la
sync
file d'attente: parce quesync
est particulièrement volatile de la file d'attente, dans laquelle les données sont propagées dans tous les sens,Ember.beginPropertyChanges()
est appelé à éviter tout observateurs de de feu, suivi par un appel àEmber.endPropertyChanges
. Il est sage: si, au cours de rinçage de lasync
file d'attente, il est tout à fait possible qu'une propriété sur un objet va changer à plusieurs reprises avant de se reposer sur sa valeur finale, et vous ne voulez pas gaspiller les ressources en immédiatement la cuisson des observateurs par tous les changements.Espère que cette aide. J'ai vraiment eu à apprendre un peu juste pour écrire cette chose, qui était le point.