如何更快地诊断JavaScript错误

分享于 

9分钟阅读

Web开发

  繁體

在10天内开发 Windows 8应用程序。

像 IE 10的现代浏览器支持 Error.stack 插件,这使得Web开发人员能够更快地诊断和纠正,尤其是那些难以复制的Web。 开发者可以利用网络平台的功能构建惊人的应用程序,它能强大现代浏览器的能力,以及在 Windows 8年的。 这些应用程序的强大功能和复杂性意味着开发人员需要更好的工具来处理错误并诊断。 在本文中,我将向你展示一些简单的调试技巧,帮助你节省时间。

调试应用程序

JavaScript中的结构错误处理处于with和 try/catch 上- 开发人员声明错误并将控制流传递给处理错误的部分。 当抛出错误时,脉轮( ) 中的JavaScript引擎捕获导致错误产生的调用链,也称作调用堆栈。 如果所抛出的对象是错误( 或者是它的Prototype链导致错误的函数),则脉轮将创建堆栈跟踪,即调用堆栈的可读列表。 这个列表被表示为错误对象上的一个属性栈。 堆栈包含错误消息。函数名和函数的源文件位置信息。 这些信息可以帮助开发人员通过学习调用哪些函数来快速诊断缺陷。 例如它可能指示传入函数的参数为空或者无效类型。

让我们以一个简单脚本为例,尝试计算两点之间的距离,( 0,2 ) 和( 12,10 ):

(function () {
 'use strict';
 function squareRoot(n) {
 if (n <0)
 thrownew 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));
 }
 try {
 sample();
 }
 catch (e) {
 console.log(e.stack);
 }
})();

这个脚本有一个 Bug - 它忘记了组件的差异。 因此,对于某些输入,pointDistance 函数将只返回不正确的结果;其他时候,它会导致错误。 要理解堆栈跟踪,让我们检查 F12开发人员工具中的错误,并查看它的脚本选项卡:

堆栈跟踪被转储到catch子句中,因为它位于栈的顶部,很明显错误发生在 squareRoot 函数中。 若要调试问题,开发人员不必深入堆栈跟踪;违反 squareRoot 前提条件,并查看堆栈为原因: 调用 squareRoot 内的子表达式本身应该是平方的参数。

调试时,堆栈属性可以帮助标识用于设置断点的代码。 记住,还有其他方法可以查看调用堆栈: 例如如果将脚本调试器设置为"中断捕获的异常"模式,则可以使用调试器检查调用堆栈。 对于部署的应用程序,可以考虑在 try/catch 中包装有问题的代码,以便捕获失败的调用,并将它们记录到。 开发人员将能够查看调用堆栈以帮助隔离问题区域。

DOM异常和 Error.stack

我以前注意到,被抛出的对象必须是一个错误或者通过它的原型链返回错误。 这是有意的;JavaScript支持抛出任何对象,甚至作为异常。 虽然所有这些都可以被捕获和检查,但它们并非全部设计为包含错误或者诊断信息。 因此,在抛出堆栈属性时,只有错误才会被更新。

尽管DOM异常是对象,但它们没有导致错误的Prototype链,因此它们没有堆栈属性。 在执行DOM操作和 Surface 兼容错误的情况下,可以能需要在 try/catch block 中包装DOM操作代码,并在catch子句中

function causesDomError() {
 try {
 var div = document.createElement('div');
 div.appendChild(div);
} catch (e) {thrownew Error(e.toString());
}
}

但是,你可能需要考虑是否要使用这里 Pattern。 它很可以能最适合用于实用程序库开发;特别是,考虑代码的意图是隐藏DOM操作。 如果是隐藏DOM操作,包装操作并抛出错误可能是正确的方法。

.性能方面考虑的因素

在抛出错误对象时,堆栈跟踪的构造开始;这样做需要遍历当前执行堆栈。 为了防止遍历特别大堆栈( 可能是递归堆栈链) 中的性能问题,IE 默认只收集最上面的10个堆栈帧。 但是,通过将 static property Error.stackTraceLimit 设置为其他值,可以配置这里设置。 这里设置是全局设置,并且必须在引发错误之前更改,否则将不会对堆栈跟踪产生影响。

异步异常

当从异步回调( 例如超时。间隔或者 XMLHttpRequest ) 生成堆栈跟踪时,异步回调而不是创建异步回调的代码将位于调用堆栈的底部。 这对跟踪有问题的代码有潜在的影响: 如果对多个异步回调使用同一个回调函数,你可能会发现很难通过检查来确定哪个回调引起了错误。 我们稍微修改一下前面的示例,这样,我们将把它放入一个超时回调中,而不是直接调用 sample():

(function () {
 'use strict';
 function squareRoot(n) {
 if (n <0)
 thrownew 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);
})();

执行这里Fragment后,你将看到堆栈跟踪在稍有延迟之后出现。 这次,你还将看到堆栈的底部不是全局代码,而是 Anonymous 函数。 实际上,它不是相同的匿名函数,而是传递给 setTimeout的回调函数。 因为丢失了环绕回调的上下文,所以你可以能无法确定调用回调的内容。 如果考虑一个方案来处理多个不同按钮的click事件,那么就不能告诉哪个回调引用了。 也就是说,这个限制只是次要的,因为在大多数情况下,堆栈的顶部可能会导致问题区域。

探索测试驱动演示

请在 Windows 8版本预览插件中使用IE10查看这个测试驱动器演示。 你可以在eval的上下文中执行代码,如果出现错误,则可以检查它。 如果在IE10中运行代码,你还可以在堆栈跟踪中停止错误行时对代码行进行 Highlight。 你可以自己在代码区域中键入代码,或者从列表中的多个示例中选择。 你还可以在运行代码示例时设置 Error.stackTraceLimit 值。

对于参考资料,你可能需要浏览到MSDN文档For以及 stackTraceLimit

这篇文章是 Rob Paveza写的。 Rob是 IE 团队的一个项目经理,他专门从事 Chakra ( 新的JavaScript运行时引擎)

HTML5视频资源


JAVA  Javascript  fast  DIA  faster  errors  
相关文章