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

IT技术 javascript jquery visual-studio debugging
2021-02-02 06:27:05

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

有没有人对此有解决方法?

6个回答

好的,结果证明该$.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>

这后一种方法并没有与我测试(视觉Studio.net,萤火虫,IE8调试器)任何调试工作。

解决方法是覆盖该$.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>
好的。自从您发布此答案后,您是否遇到过我应该注意的任何问题?;)
2021-03-20 06:27:05
此代码不适用于 $.when。任何人都知道如何解决它?
2021-04-07 06:27:05
我不认为这种方法利用了全局 ajax 事件.. 不确定。
2021-04-11 06:27:05
也许对于 shrikant 的观点,我尝试了这个,但它不适用于我想要的脚本。我四处寻找并注意到我想调试的脚本被 $.ajax() 而不是 $.getScript() 拉进来。我只是将其更改为使用 $.getScript() 一切都很酷。
2021-04-11 06:27:05
非常感谢你分享这个。它会对我有很大帮助。
2021-04-11 06:27:05

使用 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);
            }
        })
@ArashMilani 谢谢。我已经通过使用脚本的最后一个副本而不是通过 AJAX 加载它来解决它。只需检查以下内容: if(!window.MyScript){ AJAX }, else { // 调用加载函数。效果很好。
2021-03-19 06:27:05
好东西。我将 crossDomain 设置为 options.development (bool) 所以在开发时我可以调试,否则我可以忽略它。
2021-03-25 06:27:05
@SamikR 是的,这也应该有效:-) 只是我的 2 美分:恕我直言,它添加了一个if的缩进,如果我找到解决方法,我通常会避免它
2021-03-31 06:27:05
我试过这个,这似乎有效。我确实可以在调试器中看到 JS 源代码,并且可以设置断点。但是有一个问题:每次我来回切换时,都会下载一个带有新 ID # (script.js?_=2345678) 等的新 JS 文件。有什么解决方法吗?
2021-04-07 06:27:05
@SamikR 设置cache: false这样它就不会将该随机数添加到文件名的末尾
2021-04-08 06:27:05

对于那些想要调试脚本并将它们与 $.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 脚本插入及其对调试的影响

这适用于 $.when 并且脚本是完全可见和可调试的。 谢谢。

惊人的。此外,似乎 $.getScript 会阻止我缓存。切换到您的解决方案也解决了这个问题 - 这应该会为我们的客户加快速度!
2021-03-31 06:27:05
好的!直接从jquery 源代码中删除脚本没有从 DOM 中删除的小改动。
2021-04-01 06:27:05

试试这个,

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;

} 
   });

有一种简单的方法可以使用 Chrome 对其进行调试。

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

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

样本日志

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

4- 在该行上设置断点。

您可以使用关键字“调试器;” 在要调试代码的行中。
2021-03-19 06:27:05