2009-12-11 8 views
14

Je développe JS qui est utilisé dans un framework web, et fréquemment mélangé avec le code jQuery d'autres développeurs (souvent sujet aux erreurs). Malheureusement, les erreurs dans leurs blocs jQuery (document) .ready empêchent l'exécution du mien. Prenez l'exemple simple suivant:Gestion des erreurs dans jQuery (document) .ready

<script type="text/javascript"> 
    jQuery(document).ready(function() { 
     nosuchobject.fakemethod();  //intentionally cause major error 
    }); 
</script> 
<script type="text/javascript"> 
    jQuery(document).ready(function() { 
     alert("Hello!");     //never executed 
    }); 
</script> 

Le deuxième bloc prêt ne doit-il pas s'exécuter indépendamment de ce qui s'est passé dans le précédent? Existe-t-il un moyen "sûr" d'exécuter jQuery (document) .ready qui s'exécutera même dans le cas d'erreurs précédentes?

EDIT: Je n'ai aucun contrôle/visibilité sur les blocs sujettes aux erreurs car ils sont écrits par d'autres auteurs et mélangés arbitrairement.

Répondre

13

Je n'ai pas essayé ce code, mais il devrait fonctionner (au moins, l'idée devrait de toute façon). Assurez-vous de l'inclure APRES jquery, mais AVANT tout script potentiellement buggé. (Pas nécessaire, voir les commentaires.)

var oldReady = jQuery.ready; 
jQuery.ready = function(){ 
    try{ 
    return oldReady.apply(this, arguments); 
    }catch(e){ 
    // handle e .... 
    } 
}; 
+0

Cela semble fonctionner plutôt bien, que ce soit avant ou après les scripts potentiellement buggés. Je pense que ce que je vais faire est de déplacer le contenu de mon bloc ready (alerte ("Bonjour!") Dans l'échantillon) juste après le bloc catch. De cette façon, mon bloc prêt peut "s'ajouter" à la fin des blocs prêts précédents. – 3hough

+0

Excellente solution. Je n'ai jamais pensé à ça. –

+0

Je ne suis pas sûr de ce que je pensais, mais cela fonctionnera peu importe où il se passe, tant qu'il est dans la balise et non dans un événement onload, puisque nous détournons la méthode ready avant qu'elle ne soit invoquée sur dom charge. – jvenema

1

Avez-vous tenté d'encapsuler les commandes sujettes aux erreurs dans try ... catch brackets?

$(function(){ 
    try { 
     noObject.noMethod(); 
    } catch (error) { 
     // handle error 
    } 
}); 

$(function(){ 
    try { 
     alert("Hello World"); 
    } catch (error) { 
     // handle error 
    } 
}); 

Pour éviter toute confusion potentielle, $(function(){ ... }); est fonctionnellement le même que $(document).ready(function(){ ... });

+0

Le problème est que je n'ai pas le contrôle/visibilité sur les blocs qui jettent les erreurs. Dans l'exemple ci-dessus, le premier bloc jQuery (document) .ready provient du code de quelqu'un d'autre. Donc, malheureusement, je n'ai pas le moyen de les emballer dans des blocs try/catch. Cela fait partie d'un framework web où des plugins arbitraires peuvent être chargés ensemble dans la tête du document. – 3hough

+2

Vous devez mentionner dans votre question que vous n'avez pas accès à leur code. – Sampson

-2

Vous pourriez reréférencer jQuery avant chacun de vos blocs de code. Votre code utiliserait alors la nouvelle instance de la bibliothèque, et il serait exécuté. J'ai testé cela dans Safari 4.0.3 sur OSX.

<html> 
<head> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script> 
    <script type="text/javascript"> 
     jQuery(document).ready(function() { 
            nosuchobject.fakemethod();       //intentionally cause major error 
        }); 
    </script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>  
    <script type="text/javascript"> 
        jQuery(document).ready(function() { 
            alert("Hello!");                 //executed! 
        }); 
    </script> 

</head> 
<body> 

<p>hello world</p> 

</body> 
</html> 
+0

Une idée terrible ... cela forcera à tout le moins l'utilisateur à télécharger la bibliothèque deux fois, et pourrait aussi causer des problèmes avec les variables statiques et les objets qui sont écrasés. – jvenema

+0

Le navigateur de l'utilisateur télécharge à nouveau le fichier distant uniquement lorsqu'un cache cache est mis en place.Dans mon exemple, le navigateur lit la deuxième référence jQuery à partir du cache. Ce n'est pas joli, mais cela aide à résoudre le problème original. En ce qui concerne les problèmes avec les variables statiques et les objets, voulez-vous dire dans la bibliothèque jQuery elle-même, ou les variables et objets statiques définis par l'utilisateur? En cas d'écrasement, jQuery est mappé sur lui-même. Dans mon exemple, le deuxième bloc correctement écrit ferait référence à l'instance de jQuery. Pouvez-vous élaborer sur les problèmes que vous mentionnez? Merci! – simeonwillbanks

+0

Dès le début de jquery, vous verrez ceci: jQuery.fn = jQuery.prototype = {...}. Puisque ces objets ne sont pas étendus mais sont instanciés, tout ce qui modifie ou touche ces propriétés (et en fait toute autre chose définie de manière statique au niveau jquery) sera saccagé. Et même si le navigateur a mis en cache les js, il devra encore les analyser et recharger tous les éléments déclarés, ce qui dégradera l'expérience de l'utilisateur (sans parler de l'introduction de fuites de mémoire car il n'y a pas de nettoyage événements). – jvenema

2

Pour répondre à votre question, les deux blocs ready sont essentiellement combinés en un seul étant donné la façon dont fonctionne jQuery:

<script type="text/javascript"> 
    jQuery(document).ready(function() { 
     nosuchobject.fakemethod();  //intentionally cause major error 
     alert("Hello!");     //never executed 
    }); 
</script> 

Voilà pourquoi son pas alerte par l'erreur ci-dessus. Je ne crois pas qu'il existe un moyen de résoudre ce problème pour que chaque fonction ready s'exécute indépendamment des échecs précédents.

1

est ici solution, il envelopper toute fonction envoyée à prêt avec bloc try-catch:

(function($){ 
    $.fn.oldReady = $.fn.ready; 
    $.fn.ready = function(fn){ 
     return $.fn.oldReady(function(){ try{ if(fn) fn.apply($,arguments); } catch(e){}}); 
    } 
})(jQuery);