2010-04-26 4 views
2

En utilisant jQuery, j'ai créé un rotateur image/diapositive. La configuration de base est (en pseudocode):Arrête une fonction javascript récursive en cours d'exécution

function setupUpSlide(SlideToStartWith){ 
    var thisSlide = SlideToStartWith; 
    ...set things up... 
    fadeInSlide(thisSlide) 
} 

function fadeInSlide(thisSlide){ 
    ...fade in this slide... 
    fadeOutSlide(thisSlide) 
} 


function fadeOutSlide(thisSlide){ 
    ...fade out this slide... 
    thisSlide.fadeOut(fade, function() { 
    var timeout2 = setTimeout(setupUpSlide(nextSlide),100); 
    } 

J'appelle la première fonction et passer dans un index de diapositive, puis il le fait de sa chaîne d'appel chose de fonctions qui alors, à son tour, appelle à nouveau la première fonction passant dans l'index suivant. Cela se répète alors indéfiniment (en réinitialisant l'index quand il arrive au dernier élément).

Cela fonctionne très bien.

Ce que je veux faire maintenant, c'est permettre à quelqu'un de dépasser le diaporama en étant capable de cliquer sur un numéro de diapositive particulier. Par conséquent, si la diapositive n ° 8 est affichée et que je clique sur n ° 3, je souhaite que la récursion s'arrête puis appelez la fonction initiale passant dans la diapositive n ° 3, qui à son tour relancera le processus.

Mais je ne suis pas sûr de savoir comment y arriver. Comment peut-on «casser» un script récursif? Devrais-je créer une sorte de variable globale 'watch' qui, si à tout moment est 'true', retournera: false et permettra à la nouvelle fonction de s'exécuter?

MISE À JOUR: Ajout de code plus détaillé montrant appel setTimeout

Répondre

7

Utilisation de récursivité pour mettre en œuvre un diaporama est probablement pas une bonne idée, car il finira par donner une stack overflow.

Utilisez plutôt timeouts.

setTimeout() - exécute un code un certain temps dans l'avenir

clearTimeout() - Active le setTimeout()

Ou intervals:

(merci Ricket pour avoir signalé!)

La méthode setInterval() appelle une fonction ou évalue une expression à des intervalles spécifiés (en millisecondes).

La méthode setInterval() continuera à appeler la fonction jusqu'à ce que clearInterval() soit appelée ou que la fenêtre soit fermée.

+0

À un certain point, cependant, n'ai-je pas besoin de la récursivité pour continuer la boucle? Autrement dit, si j'ai 6 diapositives, je dois aller de 1 à 6, puis répéter. En utilisant les méthodes Timeout ci-dessus, comment intégrer la logique for-loop pour incrémenter les appels? –

+0

@DA: En utilisant les délais d'expiration, vous pouvez créer une boucle infinie sans provoquer de débordement de pile. Chaque appel représente une étape dans votre boucle. –

+0

ack. Aurait dû regarder ce que j'avais déjà plus près. Il s'avère que nous utilisons une fonction setTimeout dans la dernière fonction (qui à son tour appelle le premier). J'ai mis à jour l'exemple de code dans le message d'origine. Est-ce tout ce qu'il faut pour éviter le problème de débordement de la pile? –

0

au lieu de récursion indirecte, essayez d'utiliser un délai d'attente récurrent (var timer_id = setInterval(...)) et utiliser clearTimeout quand vous voulez arrêter

+0

initTimeout? veux-tu dire setInterval? (et clearInterval correspondant) – Ricket

+0

oui, mon erreur – matei

0

Voici un moyen facile de le faire. Tout d'abord, au lieu d'appeler les fonctions directement, utilisez window.setTimeout(function(){...}) à la fin de chaque fonction, en remplaçant le ... par la dernière ligne (qui fait l'appel récursif). Cela empêchera le débordement de la pile. Deuxièmement, fournissez un moyen de communiquer avec la boucle. Votre variable de veille booléenne est une bonne idée. Il n'a pas besoin d'être global, juste quelque chose que la fonction liée à votre gestionnaire de clic et les fonctions de diaporama ont tous deux accès à - une variable de classe statique, par exemple. Regardez cette variable pour les changements et briser la boucle; ou, avoir la variable être la diapositive actuellement mis en place. Etre facile, cela ne veut pas dire que c'est le meilleur meilleur pour le faire.D'une part, vos appels d'animation JQuery sont asynchrones, et vous devez utiliser leurs fonctions de rappel au lieu de la façon dont vous le faites ici, ou toutes les animations vont se produire à la fois. Vous pouvez faire tout cela dans l'espace d'un seul appel de fonction dans une fonction. JQuery permet d'enchaîner vos animations, et il vous permet également d'émettre une commande stop à n'importe quelle animation existante. Je regarderais dans cette façon de le faire d'abord au lieu de continuer avec la configuration que vous avez maintenant.

Questions connexes