2009-12-18 4 views
1

Alors que j'ai le problème lui-même apparemment résolu, je suis en espérant que quelqu'un peut faire la lumière sur la pourquoi de cette ...jQuery .remove() appel en rappel déclenche boucle infinie

Voici deux instantanés de la même fonction dont le travail consiste à supprimer un div contenant un message de retour d'utilisateur. Il est configuré pour utiliser un timeout optionnel, si un timeout est spécifié, il fait un appel à lui-même en utilisant setTimeout() qui supprime alors le div.

La seule différence entre les deux versions de la fonction est où this.remove() est appelé - dans la version problème que j'envoie un message au journal à l'aide blackbirdjs d'abord, puis appeler this.remove() - après ceci exécute le journal est submergé avec les messages sans fin de "Suppression de commentaires div ..." aussi vite que le navigateur peut les pomper.

Dans la version de travail, cependant, il suffit d'inverser l'ordre et tout s'exécute normalement et tout est bien ...

Je suis bogué, je pense que l'ordre dans ce cas serait trivial mais apparemment pas. Quelqu'un peut-il nous éclairer sur la raison pour laquelle cela se produirait? Est-ce un bug jQuery ou un problème avec blackbird ou une sorte de bizarre bizarrerie de JavaScript en général?

REMARQUE:
J'ai eu quelques succès mitigé à l'aide d'un appel pour confirmer() - si elle est revenue faux Je l'ai dit de revenir et cela l'a arrêté - cependant, le simple ajout retour après l'appel de suppression n'a eu aucun effet .

Il est intéressant de noter que l'une ou l'autre des versions semble fonctionner correctement dans IE8 - cela peut donc être un problème de firefox/gecko?

Code Problème:

function clear_feedback(target_container, timeout){ 
    log.debug("timeout: " + timeout); 
    log.debug("target_container: " + target_container); 

    if(timeout == undefined){ 
     log.info("removing target..."); 

     $(target_container).children(".update_feedback").slideUp("slow", 
      function() { 
       log.info("Removing feedback div..."); 
       this.remove(); 
      } 
     ); 
    } 
    else{ 
     log.info("Setting timeout, THEN removing target..."); 

     setTimeout("clear_feedback('" + target_container + "')", timeout); 
    } 
} 

Code du travail:

function clear_feedback(target_container, timeout){ 
    log.debug("timeout: " + timeout); 
    log.debug("target_container: " + target_container); 

    if(timeout == undefined){ 
     log.info("removing target..."); 

     $(target_container).children(".update_feedback").slideUp("slow", 
      function() { 
       this.remove(); 
       log.info("Removing feedback div..."); 
      } 
     ); 
    } 
    else{ 
     log.info("Setting timeout, THEN removing target..."); 

     setTimeout("clear_feedback('" + target_container + "')", timeout); 
    } 
} 

Répondre

1

Vous auriez dû vérifier la console d'erreur de votre navigateur au lieu de simplement vous fier à la console blackbirdjs.

Ensuite, vous auriez remarqué que la console d'erreur de navigateurs est inondé de messages d'erreur trop (avec l'une de vos versions de code)

Le problème réel dans votre code est

this.remove(); 

this est un HTML DOM élément dans la fonction de rappel et n'a pas la fonction remove() ainsi les enfants ne sont cachés mais pas vraiment effacés. Et sur this.remove() vous obtenez une exception. Comme la fonction de rappel lance une exception jQuery se retrouve dans une boucle sans fin essayant de faire son travail

Ce que vous devez faire est d'enrouler l'élément dans un objet jQuery.

$(this).remove(); 

Maintenant, il est clair aussi pourquoi la deuxième version semble avoir corrigé l'erreur

log.info("Removing feedback div..."); //error logged 
this.remove(); //exception 

this.remove(); //exception 
//log line not executed as previous line threw exception 
log.info("Removing feedback div..."); 

Le fait que jQuery se termine même dans et boucle sans fin et si cela est correct le comportement est discutable et nécessite plus d'investigations plus approfondies dans le fonctionnement interne de jQuery. Mais cela ne vous intéresse

Pour les intéressés il y a billet bug Realted

http://dev.jquery.com/ticket/2846

+0

gah ..../head-slam-on-desk Je n'ai pas encore eu l'occasion de le tester et je ne le ferai probablement pas pour le prochain (j'ai pris un congé annuel pour les vacances de Noël à partir de vendredi), mais après avoir lu ceci l'erreur semble être assez claire ... erreur de débutant. –

+0

Désolé pour le long délai - le premier jour de retour au travail. Merci beaucoup! –

0

J'ai vu un problème comme cela, mais dans un contexte différent; Cependant, je soupçonne que la cause première est la même.

Si vous jetez un oeil à log.info, vous verrez qu'il insère un noeud dans le DOM. Si l'une des fonctions jquery arrive à traverser le DOM dans le bon emplacement, en particulier, juste à l'endroit où log.info insère le nœud, et si cela provoque l'appel de votre callback, votre callback insérera un autre nœud, et vous vous retrouvez dans une boucle infinie. La question de savoir pourquoi cela ne se produit pas dans IE8 est probablement l'une des deux raisons: soit la structure du DOM n'est pas exactement la même entre les navigateurs, soit IE8 utilise une stratégie différente pour gérer l'insertion du nœud DOM pendant le javascript le code traverse l'arbre.

Vous pouvez essayer d'utiliser Firebug, en plaçant des points d'arrêt autour des lignes problématiques, puis en visualisant l'arborescence DOM pour voir si vous pouvez détecter un comportement comme celui-ci.

+0

Cool - merci pour l'info - Je vais mener des enquêtes et vous laisser savoir ce que, si quelque chose, je trouver. –