调试脚本通过jQuery getScript函数添加

时间:2009-03-27 17:44:57

标签: javascript jquery visual-studio debugging

我有一个页面,通过jQuery的$.getScript函数动态添加脚本引用。脚本加载并执行正常,所以我知道引用是正确的。但是,当我向任何脚本添加“调试器”语句以允许我在调试器(例如VS.Net,Firebug等)中单步执行代码时,它不起作用。似乎jQuery加载脚本的方式阻止了调试器查找文件。

有人为此做了解决方法吗?

9 个答案:

答案 0 :(得分:74)

好的,事实证明$.getScript()函数的默认实现工作方式不同,具体取决于引用的脚本文件是否在同一个域中。外部参考如:

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

将导致jQuery创建一个外部脚本引用,可以毫无问题地进行调试。

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

但是,如果您引用本地脚本文件,例如以下任何一种:

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

然后jQuery将异步下载脚本内容,然后将其添加为内联内容:

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

后一种方法 不能与我测试的任何调试器一起工作(Visual Studio.net,Firebug,IE8 Debugger)。

解决方法是覆盖$.getScript()函数,以便始终创建外部引用而不是内联内容。这是执行此操作的脚本。我已经在Firefox,Opera,Safari和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>

答案 1 :(得分:18)

使用JQuery 1.6(可能是1.5),您可以切换到不使用getScript,但使用jQuery.ajax()。然后设置crossDomain:true,你将获得相同的效果。

错误回调无效。所以你不妨把它设置得如下。

但是,我确实设置了一个计时器并成功清除它。所以说10秒后,如果我什么也听不到,我认为文件不好。

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

答案 2 :(得分:14)

对于那些想要调试脚本并使用$ .when的人(James Messinger的答案与$ .when不兼容)我建议使用此代码:

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();
};

所有的荣誉和荣耀归于Benjamin Dumke-von der Ehe和他的文章:jQuery script insertion and its consequences for debugging

这适用于$ .when,脚本完全可见且可调试。 感谢。

答案 3 :(得分:2)

试试这个,

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;

} 
   });

答案 4 :(得分:2)

使用Chrome可以轻松调试它。

1-在要调试的行上写一个console.log(“something”)。

2-观察该日志的控制台。

sample log

3-单击日志前面的地址链接。

4-在该行设置断点。

答案 5 :(得分:0)

为避免大量额外编码,您可以试试这个。在您声明$('document').ready()(或调试器将访问的任何其他文件)的文件中,添加类似......

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

在调试器的分配行中添加断点。然后,在使用$ .getScript()加载的任何其他js文件中,您可以添加...

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

每当执行此行时,调试器将停止并等待您的命令。退出$ .debug函数,就是这样!

答案 6 :(得分:0)

在使用Firebug 2.0.14的Firefox 38.6.0中,当我转到“脚本”选项卡时,我在下拉菜单中看到一个条目,如jquery-1.11.1.js line 338 > eval,其中包含已加载的脚本。另外,看看这个版本的jQuery中的代码,看起来内部$.getScript()正在使用$.get()并最终使用$.ajax(),唯一的区别是脚本的eval()部分,由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 );
    }
},

答案 7 :(得分:0)

这将OP解决方案与Eric的解决方案结合在一起。覆盖必要的jquery来处理始终是crossdomain并且它们将完美地显示出来而不会破坏jquery promise实现中的单个事物。

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
 });
}


});

答案 8 :(得分:0)

所有答案都在本页的某个位置,但我想为以后的读者进行总结。

检查(动态添加的)文件下载

使用Chrome,您可以在XHR标签上的网络面板下看到使用$ .getScript(http://api.jquery.com/jQuery.getScript/)添加的Javascript文件;请注意,它们不会出现在“ JS”标签下。

调试文件

1)在代码中设置断点。如其他答案\评论中所述,您可以插入

debugger;
Java代码中的

语句。这将调用浏览器的调试器。有关更多信息,请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger

2)使用源地图使其显示在浏览器的“源”面板中(在Chrome中进行测试)。添加

//# sourceURL=whatevername.js

到文件末尾。 [文件显示在Chrome源代码面板中的(无域)下。]

请参阅: How to debug dynamically loaded JavaScript (with jQuery) in the browser's debugger itself?https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map了解更多信息。

3)覆盖$ .getScript以始终根据接受的答案使用外部引用(我尚未测试)。