Infini Boucle de Minuterie avec javascript ( pas de setInterval)?
M'a demandé (par un ami) pour construire un timer (infini qui écrit une ligne à chaque seconde), mais sans setInterval
.
Je résolu avec :
var i = 0;
function k(myId, cb)
{
setTimeout(function ()
{
console.log(myId);
cb();
}, 1000);
}
function go()
{
i++;
k(i, go);
}
go();
Et il est de travail.
Le problème est que j'ai peur, il va y avoir une pression sur la mémoire. Il crée en fait une récursivité et après un certain temps (une semaine ou quelque chose) - le processus de consommer beaucoup de mémoire. (la pile n'est jamais libéré)
Comment puis-je changer mon code afin de ne pas être beaucoup de mémoire consommer?
"j'ai peur qu'il va y avoir une pression de mémoire" - Vous êtes inquiet qu'il peut être, ou vous l'ai testé et il est? Vous mentionnez fonctionner pour un week - avez-vous réellement le faire et ont un problème? Comme mentionné dans les réponses ci-dessous ce n'est pas la récursivité. Aussi, pourquoi la triple fonction de la configuration avec
go()
et k()
et la fonction anonyme? Vous pourriez faire la console.log()
dans go()
et puis ne setTimeout(go,1000)
.
OriginalL'auteur Royi Namir | 2012-11-22
Vous devez vous connecter pour publier un commentaire.
Ce n'est pas la récursivité
Il peut ressembler à la récursivité, mais setTimeout ne crée pas la récursivité.
La façon setTimeout œuvres, c'est qu'il revient tout de suite. Donc, l'appel à
k
se termine immédiatement avec sa pile libéré.Lorsque le délai d'attente se produit réellement et l'appel à
go
se produit à nouveau, il n'est pas du point de l'appel précédent dek
mais à partir de la portée mondiale*.* Note: je ne suis pas en utilisant le sens strict du champ d'application défini à ECMAScript spec ici. Ce que je veux dire, c'est l'appel à
k
sera faite que si vous avez écrit dans une plaine<script></script>
tag: c'est-à-dire, en dehors de toutes les autres appels de fonction.Concernant votre inquiétude sur la fermeture
Dans votre cas particulier, il y a très peu de choses sont réellement contenu dans la fermeture créé par le
k
fonction. La seule fermeture est la référence pour les argumentscb
etmyId
. Et même alors, il ne dure que pendant environ une seconde:De plus simple
Je note que votre code est assez complexe. Il peut être écrit plus simple, et sans l'aide de fermetures à tous (moins la variable globale i) si vous avez simplement l'écrire comme ceci:
go
arrive de nouveau, il commence avec une nouvelle pile vide. Il ne continue pas à ajouter à la pile précédent.""mais à partir de la portée mondiale" - ce n'est pas tout à fait droit. Ce sujet de la fermeture de l'appel précédent à
k
? La fonction anonyme transmise àsetTimeout()
utilise l'un des paramètres dek()
, de sorte que même sik()
a terminé l'exécution de pièces de il encore traîner au moins pour un temps...pouvez-vous expliquer cela ?
Clarifier ce que je voulais dire. N'utilisez pas vos mots, parce que même si le libellé est techniquement faux, je trouve que plus de gens à saisir le concept plus rapidement de cette façon.
Lire ma réponse à cette question: stackoverflow.com/questions/13301050/... . C'est à propos de XMLHttpRequest au lieu de setTimeout mais il y a une belle ASCII ART schéma qui explique comment la boucle d'événement fonctionne dans les navigateurs et qui s'applique à setTimeout.
OriginalL'auteur slebetman
Cette ligne est fausse:
Il ne pas créer une récursivité, parce que la fonction des sorties complètement et est alors appelé à nouveau.
La récursivité des piles sur le dessus de chaque autre
La pile ressemble à ceci
Avec setTimeout, vous devez exécuter une fonction. Cette fonction met en place un événement pour la fonction à exécuter à nouveau-mais ici, c'est la différence importante: La fonction se termine, complètement, et est parti[1]. PUIS il est appelé de nouveau.
Exécution sage, il n'est pas très différent de le faire:
setTimeout
donne juste le navigateur une chance de "respiration" si vous. Une chance pour l'écran de mise à jour, d'autres événements à traiter. Ce n'est pas, pour utiliser la terminologie appropriée,block
le navigateur.setTimeout
appel crée un fermeture à l'extérieur de la fonction, le contexte d'exécution, et explicitement àcb
, il y a donc un champ d'application de la pile en cours de formation. Il peut être optimisé à l'écart depuis le seul besoin de la fermeture est à l'immédiate extérieure et un contexte mondial, mais qui est dépendant de l'implémentation et peut-être pas fiable. En tout cas, vous avez raison, il ne devrait pas créer de problèmes.Mais il y a une fermeture ici....de la sorte ? ne devrait-il pas être un problème ?
Belle réponse. J'aime la
a();a();a()
exempleune fermeture entre la fonction anonyme transmise à
setTimeout
, à l'extérieurk
la fonction et l'objet global. Mais quand la fonction anonyme est appelé et a terminé l'exécution, il est (ou devrait être) disponible pour la collecte des ordures. Une nouvelle fermeture est formé avec la nouvelle fonction dans le nouveausetTimeout
, mais cela n'implique pas la précédente fermeture, c'est un tout nouveau contexte d'exécution.pouvez-vous joindre, veuillez chat.stackoverflow.com/rooms/19929/... ?
OriginalL'auteur Jeremy J Starcher
Cela ne crée pas une fuite de mémoire.
En fait, il est assez couramment utilisé concept. Il apparaît généralement sous cette forme:
Lorsque vous souhaitez vérifier quelque chose souvent (ici toutes les 10 millisecondes), il peut être préférable d'utiliser ce modèle au lieu de
setInterval
, car il peut améliorer votre performance. Par exemple, si votre fonction prend plus de 10 millisecondes à exécuter, et que vous utilisezsetInterval(f, 10)
alors il n'aura de cesse d'être appelé. Toutefois, si vous utilisez lesetTimeout
schéma ci-dessus, il aura au moins assurez-vous que le processeur obtient un 10 millisecondes entre chaque appel, peu importe combien de temps votre fonction prend à exécuter.Voir cette vidéo (à partir de 7:46) de Paul Irish pour plus d'informations sur ce modèle.
OriginalL'auteur Nathan Wall