如何调试挂起浏览器的JavaScript ?

How can you debug JavaScript which hangs the browser?

本文关键字:浏览器 JavaScript 挂起 何调试 调试      更新时间:2023-09-26

我正在开发一个非常大的富网页JavaScript应用程序。由于某些原因,最近的一次更改导致它随机挂起浏览器。

我怎样才能缩小问题的范围?由于浏览器变得无响应,我没有看到任何错误,不能使用FireBug Break on next

你应该使用调试控制台日志

您应该使用大多数现代浏览器提供的console.log()功能,或者如果您使用不支持它的浏览器,则模拟它。

每次调用console.log('sometext')时,将在浏览器的调试控制台中创建一个日志条目,其中包含指定的文本,通常后跟实际时间。

您应该在应用程序流的每个关键部分之前设置一个日志条目,然后越来越多,直到找到没有调用的日志。这意味着日志之前的代码挂起了浏览器。

您还可以编写带有附加功能的个人日志函数,例如某些特定变量的状态,或包含程序流程更详细方面的对象,等等。

console.log('step 1');
while(1) {}
console.log('step 2');

无限循环将停止程序,但您仍然可以看到控制台日志,其中记录了程序流程,直到程序停止。

所以在这个例子中,你不会在控制台日志中看到"步骤2",但是你会看到"步骤1"。这意味着程序在步骤1和步骤2之间停止。

然后可以在两个步骤之间的代码中添加额外的控制台日志,以深入搜索问题,直到找到它为止。

我很惊讶这个问题还没有得到适当的回答,大多数人投票的答案基本上是"把控制台日志放在任何地方,直到你弄清楚为止",这并不是一个真正的解决方案,特别是对于大型应用程序,除非你真的想花所有的时间复制粘贴"控制台日志"。

无论如何,你所需要的是debugger;有人已经提到了这一点,但并没有真正解释它如何使用:

在chrome(和大多数其他浏览器)中,debugger;将停止执行,带您到开发控制台,并在左侧显示当前执行的代码,在右侧显示堆栈跟踪。在控制台的右上角有一些箭头状的按钮。第一个是"恢复脚本执行"。我们想要的是下一个"超越下一个函数调用"。

基本上,你所需要做的就是把调试器放在代码的任何地方,在你知道页面还没有冻结的地方,然后运行它,反复点击"跳过下一个函数调用",这看起来就像一个箭头跳过一个圆圈。它将逐行,调用一个又一个调用,通过脚本的执行,直到它挂起/陷入无限循环。此时,您将能够准确地看到代码卡住的位置,以及当前范围内的所有变量/值,这应该有助于您理解脚本卡住的原因。

我只是绞尽脑汁,试图在一些相当复杂的JS中找到一个悬挂循环,我使用这种方法在大约30秒内找到了它。

你可以在JS代码的任何地方添加debugger;来手动设置断点。它将暂停执行,并允许您恢复/检查代码(Firebug/FF)。

Firebug Wiki页面:http://getfirebug.com/wiki/index.php/Debugger;_keyword

今天的浏览器Firefox/Seamonkey (Ctrl-Shift-I/Debugger/PAUSE-Icon), Chrome,…通常有一个内置的JS调试器,带有PAUSE按钮,可以随时工作。在循环/cpu密集的页面上,只需点击它,很可能"调用堆栈"类型的窗格将指向问题-准备进一步检查…

要隔离问题,您可以从删除/禁用/注释代码的不同部分开始,直到您将代码缩小到可以让您找到错误的一小部分。另一种可能性是查看最近提交的不同更改的源代码控制签入历史。

安装Google Chrome,进入你的页面,按f12,开发者控制台将弹出。然后选择Scripts按钮,然后从控制台左上角的下拉菜单中选择脚本(例如:myScript.js)。然后单击第一行(或您认为不会挂起的行),将生成一个断点。javascript到达断点后,单击控制台右上角的一个按钮(您将看到一个类似暂停符号的按钮,然后是其他4个按钮)。按2º按钮(或暂停后跨步按钮)或3º按钮(跨步)。鼠标放在按钮上,他们会向你解释他们的意思。然后你将像这样进入你的代码,直到它挂起,然后你可以更好地调试它。

Google Chrome调试器比firebug好得多,而且更快。我从firebug中做出了改变,这真的很棒!

我知道这是原始的,但我喜欢用'alert's来点缀我的js代码,看看我的代码在问题发生之前走了多远。如果警告窗口太烦人,您可以设置一个文本区域,您可以添加日志:

<textarea id='txtLog' ...></textarea>
<script>
...
function log(str) {
    $('#txtLog').append(str + ''n');
}
log("some message, like 'Executing Step #2'...");
...
</script>

根据我的经验,导致浏览器无响应的问题通常是无限循环或类似的。

作为一个起点,检查你的循环是否有愚蠢的事情,比如不增加你以后依赖的东西。

正如之前的一个帖子所说,除此之外,注释掉一些代码来隔离问题。你"可以"使用分而治之的方法,几乎逐字注释掉一半的JS页面,如果它能处理不同的错误,你可能找到了正确的部分!

然后把它分成两半,等等,直到你找到罪魁祸首。

我认为你可以这样使用控制台日志

console.log(new Date() + " started Function Name or block of lines from # to #");
// functions or few lines of code
console.log(new Date() + " finished Function Name or block of lines from # to #")

在运行网页结束时,您可以识别在执行过程中花费大量时间的区域,b

除了使用手动日志输出和debugger之外,有时记录每个函数调用以跟踪循环发生的位置可能会有所帮助。下面这段代码来自自动将console.log添加到每个函数中,这样做可能会派上用场…

function augment(withFn) {
    var name, fn;
    for (name in window) {
        fn = window[name];
        if (typeof fn === 'function') {
            window[name] = (function(name, fn) {
                var args = arguments;
                return function() {
                    withFn.apply(this, args);
                    return fn.apply(this, arguments);
                }
            })(name, fn);
        }
    }
}
augment(function(name, fn) {
    console.log("calling " + name);
});

我知道这个问题很老了,但在VS2013中,您可以按下暂停按钮并获得完整的JS堆栈跟踪。这让我很抓狂,因为循环是在角内的,所以我不能真正地放入警报、断点等,因为我不知道把它们放在哪里。我不知道它是否适用于免费快速版,但值得一试。

我也读到Chrome有暂停功能,所以这可能是一个选项,但我自己没有尝试过。

我遇到了同样的问题,我就是这样解决的。

  1. 检查控制台的错误并修复它们

有时控制台甚至挂起

  • 检查所有循环,如果一个是无限的
  • 检查递归代码
  • 检查动态添加元素到文档
  • 的代码
  • 在控制台使用断点
  • 使用一些控制台日志,例如记录可疑的代码块
  • 我在这些答案中没有真正看到的是你可以这样做:

    let start;
    let end;
    //This would represent your application loop.
    while (true) {
      start = performance.now();
      //Loop code.
      //...
      end = performance.now();
      //Measured in ms.
      if (end - start > 1000) {
        //Application is lagging! Etc.
      }
    }
    

    通过这种方式,您也许可以检测到应用程序何时开始表现不佳等。

    https://developer.mozilla.org/en-US/docs/Web/API/Performance/now