web-dev-qa-db-fra.com

Scripts de débogage ajoutés via la fonction getScript de jQuery

J'ai une page qui ajoute dynamiquement des références de script via la fonction $.getScript de jQuery. Les scripts se chargent et s’exécutent correctement. Je sais donc que les références sont correctes. Cependant, lorsque j'ajoute une instruction "débogueur" à l'un des scripts pour me permettre de parcourir le code dans un débogueur (tel que VS.Net, Firebug, etc.), cela ne fonctionne pas. Il semble que quelque chose dans la manière dont jQuery charge les scripts empêche les débogueurs de trouver les fichiers.

Quelqu'un at-il une solution pour cela?

49
James Messinger

Ok, il s’avère que l’implémentation par défaut de la fonction $.getScript() fonctionne différemment selon que le fichier de script référencé se trouve ou non sur le même domaine. Références externes telles que:

$.getScript("http://www.someothersite.com/script.js")

jQuery créera une référence de script externe, qui peut être déboguée sans problèmes.

<script type="text/javascript" src="http://www.someothersite.com/script.js"></script>

Toutefois, si vous faites référence à un fichier de script local tel que l’un des suivants:

$.getScript("http://www.mysite.com/script.js")
$.getScript("script.js")
$.getScript("/Scripts/script.js");

alors jQuery téléchargera le contenu du script de manière asynchrone, puis l'ajoutera en tant que contenu intégré:

<script type="text/javascript">{your script here}</script>

Cette dernière approche ( ne fonctionne pas avec tous les débogueurs que j'ai testés (Visual Studio.net, Firebug, débogueur IE8).

La solution de contournement consiste à remplacer la fonction $.getScript() afin qu'elle crée toujours une référence externe plutôt qu'un contenu en ligne. Voici le script pour le faire. J'ai testé cela dans Firefox, Opera, Safari et IE 8.

<script type="text/javascript">
// Replace the normal jQuery getScript function with one that supports
// debugging and which references the script files as external resources
// rather than inline.
jQuery.extend({
   getScript: function(url, callback) {
      var head = document.getElementsByTagName("head")[0];
      var script = document.createElement("script");
      script.src = url;

      // Handle Script loading
      {
         var done = false;

         // Attach handlers for all browsers
         script.onload = script.onreadystatechange = function(){
            if ( !done && (!this.readyState ||
                  this.readyState == "loaded" || this.readyState == "complete") ) {
               done = true;
               if (callback)
                  callback();

               // Handle memory leak in IE
               script.onload = script.onreadystatechange = null;
            }
         };
      }

      head.appendChild(script);

      // We handle everything using the script element injection
      return undefined;
   },
});
</script>
74
James Messinger

Avec JQuery 1.6 (peut-être 1.5), vous pouvez passer à n’utilisez pas getScript, mais jQuery.ajax (). Ensuite, définissez crossDomain: true et vous obtiendrez le même effet.

Le rappel d'erreur ne fonctionnera pas. Donc, vous pourriez aussi bien ne pas le configurer comme ci-dessous.

Cependant, je configure une minuterie et l’efface avec le succès. Donc, dites après 10 secondes si je n'entends rien, je suppose que le fichier était mauvais.

        jQuery.ajax({
            crossDomain: true,
            dataType: "script",
            url: url,
            success: function(){
                _success(_slot)
            },
            error: function(){
                _fail(_slot);
            }
        })
18
Eric Twilegar

Pour ceux qui souhaitent déboguer des scripts et les utiliser avec $ .when (la réponse de James Messinger ne fonctionne pas bien avec $ .when), je suggère d'utiliser ce code:

var loadScript = function (path) {
  var result = $.Deferred(),
  script = document.createElement("script");
  script.async = "async";
  script.type = "text/javascript";
  script.src = path;
  script.onload = script.onreadystatechange = function (_, isAbort) {
      if (!script.readyState || /loaded|complete/.test(script.readyState)) {
         if (isAbort)
             result.reject();
         else
            result.resolve();
    }
  };
  script.onerror = function () { result.reject(); };
  $("head")[0].appendChild(script);
  return result.promise();
};

Tous les crédits et la gloire vont à Benjamin Dumke-von der Ehe et à son article: L'insertion de script jQuery et ses conséquences pour le débogage

Cela fonctionne bien avec $ .when et le script est totalement visible et debugable.Merci.

14
Alex Sorokoletov

Essaye ça,

jQuery.extend({
getScript: function(url, callback) {
    var head = document.getElementsByTagName("head")[0];

    var ext = url.replace(/.*\.(\w+)$/, "$1");

    if(ext == 'js'){
        var script = document.createElement("script");
        script.src = url;
        script.type = 'text/javascript';
    } else if(ext == 'css'){
        var script = document.createElement("link");
        script.href = url;
        script.type = 'text/css';
        script.rel = 'stylesheet';
    } else {
        console.log("Неизветсное расширение подгружаемого скрипта");
        return false;
    }



    // Handle Script loading
    {
        var done = false;

        // Attach handlers for all browsers
        script.onload = script.onreadystatechange = function(){
            if ( !done && (!this.readyState ||
            this.readyState == "loaded" || this.readyState == "complete") ) {
                done = true;
                if (callback)
                callback();

                // Handle memory leak in IE
                script.onload = script.onreadystatechange = null;
            }
        };
    }

    head.appendChild(script);

    // We handle everything using the script element injection
    return undefined;

} 
   });
2
alexpts

Il existe un moyen simple de le déboguer avec Chrome.

1- Ecrivez un fichier console.log ("quelque chose") sur la ligne que vous souhaitez déboguer.

2- Surveillez ce journal sur la console.

sample log

3- Cliquez sur le lien d'adresse devant le journal.

4- Définir le point d'arrêt sur cette ligne.

1
DaNeSh

Toutes les réponses sont quelque part sur cette page, mais je voulais résumer pour les futurs lecteurs.

Vérification des téléchargements de fichiers (ajoutés dynamiquement)

Avec Chrome, vous pouvez voir les fichiers Javascript ajoutés à l'aide de $ .getScript ( http://api.jquery.com/jQuery.getScript/ ) dans le panneau Réseau de l'onglet XHR; notez qu'ils n'apparaissent pas sous l'onglet JS.

Débogage du fichier

1) Définition d’un point de rupture dans le code. Comme mentionné dans d'autres réponses\commentaires, vous pouvez insérer un 

debugger;

déclaration dans le code Javascript. Cela invoquera le débogueur du navigateur. Voir https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger pour plus d'informations.

2) Utilisation d'un Carte source pour le faire apparaître dans le panneau Sources du navigateur (test sous Chrome) .Ajouter 

//# sourceURL=whatevername.js

à la fin de votre dossier. [Le fichier apparaît sous (no-domain) dans le panneau source de Chrome].

Voir: Comment déboguer du JavaScript chargé dynamiquement (avec jQuery) dans le débogueur du navigateur lui-même? et https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map pour plus d'informations.

3) Ignorez $ .getScript pour toujours utiliser une référence externe conformément à la réponse acceptée (je n'ai pas encore testé). 

0
Anthony

Cela combine la solution OP avec celle d’Eric. Remplacer le jQuery nécessaire pour traiter devient comme toujours multi-domaines et ils apparaîtront parfaitement sans casser une seule chose dans la mise en œuvre de la promesse JQuery.

jQuery.extend({
get: function (url, data, callback, type) {
 // shift arguments if data argument was omitted
 if (jQuery.isFunction(data)) {
    type = type || callback;
    callback = data;
    data = undefined;
 }

 return jQuery.ajax({
    url: url,
    type: "GET":,
    dataType: type,
    data: data,
    success: callback,
    crossDomain: true
 });
}


});
0
osoblanco

Pour éviter beaucoup de codage supplémentaire, essayez ceci. Dans le fichier où vous avez déclaré votre $ ('document'). Ready () ( ou tout autre fichier auquel votre débogueur aura accès ), ajoutez quelque chose du genre ...

$.debug = function(name) {
   var n = name;
}

Ajoutez un point d'arrêt à la ligne d'affectation dans votre débogueur. Ensuite, dans tout autre fichier js que vous chargez avec $ .getScript (), vous pouvez ajouter ...

$.debug("some string to identify this point of code");

Chaque fois que cette ligne est exécutée, le débogueur s’arrête et attend votre commande. Sortez de la fonction $ .debug et c'est tout!

0
user1904991

Dans Firefox 38.6.0 avec Firebug 2.0.14, lorsque je vais dans l'onglet Script, une entrée du menu déroulant telle que jquery-1.11.1.js line 338 > eval apparaît et contient le script chargé. De plus, si vous regardez le code dans cette version de jQuery, il apparaît que $.getScript() utilise $.get() et $.ajax(), la seule différence étant la partie eval() du script, gérée par la fonction jQuery globalEval():

// Evaluates a script in a global context
// Workarounds based on findings by Jim Driscoll
// http://weblogs.Java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
globalEval: function( data ) {
    if ( data && jQuery.trim( data ) ) {
        // We use execScript on Internet Explorer
        // We use an anonymous function so that context is window
        // rather than jQuery in Firefox
        ( window.execScript || function( data ) {
            window[ "eval" ].call( window, data );
        } )( data );
    }
},
0
AsGoodAsItGets