技术开发 频道

教你如何更快的诊断JavaScript错误

  性能考虑

  当错误对象被抛出时,开始堆栈跟踪的构造;这样做需要追踪到当前执行的堆栈。为了防止在遍历一个大堆栈(或许是一个递归堆栈)时的性能问题,默认的情况下IE只收集前十的堆栈帧,当然这个设置可以配置,你可以设置静态属性Error.stackTraceLimitto为其他的值。这个配置是全局的,并且必须在错误抛出之前设置,否则它不会产生跟踪堆栈的效果。

  异步的异常

  当一个堆栈跟踪产生于一个异步的回调时(比如,timeout,interval, 或者XMLHttpRequest),异步调用,而不是在调用堆栈的底部创建异步调用的代码。这里存在一些跟踪问题代码的潜在影响:如果你对于多个异步回调使用相同的回调函数,你或许会发现很难查找出某一个单独的回调引起的错误。让我们稍微修改下之前的例子,替换直接调用simple(),采用timeout函数回调方法调用:

(function () {
    
'use strict';
    
function squareRoot(n) {
        
if (n < 0)
            
throw new Error('Cannot take square root of negative number.');
        
        
return Math.sqrt(n);
    }
    
    
function square(n) {
        
return n * n;
    }
    
    
function pointDistance(pt1, pt2) {
        
return squareRoot((pt1.x - pt2.x) + (pt1.y - pt2.y));
    }
    
    
function sample() {
      
var pt1 = { x: 0, y: 2 };
      
var pt2 = { x: 12, y: 10 };
      
       console.log(
'Distance is: ' + pointDistance(pt1, pt2));
    }
    
    setTimeout(
function () {
        
try {
            sample();
        }
        
catch (e) {
            console.log(e.stack);
        }
    },
2500);
})();

  在执行这段代码时,你会看到堆栈跟踪稍微有些延迟,这次你也会看到堆栈的底层不是全局的代码而是一个匿名函数。实际上,它们不是使用同一个匿名函数,而是回调函数传递给setTimeout,由于你失去了回调的上下文环境,你也就无法确认哪个回调被调用了。如果你考虑这样的一个场景,一个回调被注册到多个不同按钮的点击事件上,你将无法确认引用的是哪个注册的回调。那就是说,这个限制只是次要的,因为在大多数情况下,堆栈顶部会突出问题区域。

  探索测试驱动例子

  在windows8系统下使用IE10检查这个测试例子Test Drive demo。你可以使用eval执行代码,如果发生了错误,你能及时检查到它。如果你在IE10下运行它,当你把鼠标放在错误堆栈上时,错误代码行会突出显示。你可以在代码区自己输入代码,或者在列表中例子里选择一个。你也可以在运行示例代码时设置Error.stackTraceLimitvalue。

异步的异常

  作为参考资料,你可以浏览MSDN关于Error.stack和stackTraceLimit的文档。

  这篇文章作者是Rob Paveza. Rob是IE团队的一个项目经理,主要研究Chakra,一个新型的javascript运行引擎。

0
相关文章