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

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, donc je sais que les références sont correctes. Cependant, lorsque j'ajoute une instruction "debugger" à l'un des scripts pour me permettre de parcourir le code dans un débogueur (tel que VS.Net, Firebug, etc.), il ne fonctionne pas. Il semble que quelque chose sur la façon dont jQuery charge les scripts empêche les débogueurs de trouver les fichiers.

Quelqu'un a-t-il une solution pour cette?

48
demandé sur Brian Mains 2009-03-27 20:44:56

8 réponses

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

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

Entraînera la création par jQuery d'une référence de script externe, qui peut être déboguée sans problème.

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

Toutefois, si vous référencez un fichier de script local tel que l'un des éléments 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 et puis ajoutez-le en tant que contenu en ligne:

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

Cette dernière approche ne Pas Fonctionne avec n'importe quel débogueur que j'ai testé (visuel Studio.net, Firebug, débogueur IE8).

La solution 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
répondu James Messinger 2009-03-31 22:59:28

Avec jQuery 1.6 (peut-être 1.5), vous pouvez passer à ne pas utiliser getScript, mais à utiliser 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. Alors 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
répondu Eric Twilegar 2011-09-21 01:57:01

Pour ceux qui voudraient déboguer des scripts et les utiliser avec $.quand (la réponse de James Messinger ne fonctionne pas bien avec $.quand) 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: jQuery script insertion et ses conséquences pour le débogage

Cela fonctionne bien avec un $.quand et le script est totalement visible et déboguable. Grâce.

14
répondu Alex Sorokoletov 2014-02-07 20:27:35

Essayez ceci,

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
répondu alexpts 2012-11-19 06:40:08

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

1-écrire une console.log("quelque chose") sur la ligne que vous souhaitez déboguer.

2-Regardez la console pour ce journal.

exemple de journal

3-Cliquez sur le lien adresse en face du journal.

4-Définissez le point de rupture sur cette ligne.

1
répondu DaNeSh 2015-05-08 19:52:01

Pour éviter beaucoup de codage supplémentaire, vous pouvez essayer ceci. Dans le fichier où vous avez déclaré votre $('document').ready() (ou tout autre fichier auquel votre débogueur accédera ), ajoutez quelque chose comme...

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

Ajoutez un point d'arrêt à la ligne d'affectation dans votre débogueur. Ensuite, dans n'importe quel autre fichier js, 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, votre débogueur s'arrête et attend votre commande. L'étape de l' $.des fonctions de débogage et c'est tout!

0
répondu user1904991 2016-02-13 14:39:09

Dans Firefox 38.6.0 avec Firebug 2.0.14 quand je vais à L'onglet Script, je vois une entrée dans le menu déroulant comme jquery-1.11.1.js line 338 > eval et qui contient le script chargé. De plus, en regardant le code dans cette version de jQuery, il semble qu'en interne $.getScript() utilise $.get() et finalement $.ajax(), la seule différence étant la partie eval() pour le script, qui est 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
répondu AsGoodAsItGets 2016-02-25 17:21:03

Cela combine la solution OP avec celle D'Eric. Remplacez le jquery nécessaire pour traiter gets comme toujours crossdomain et ils apparaîtront parfaitement sans casser une seule chose dans l'implémentation 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
répondu osoblanco 2016-04-27 14:35:42