Javascript错误处理的最佳实践

Javascript错误处理的最佳实践
不管你的技术水平,错误或异常是一个应用程序开发人员的生活的一部分,Web开发不留下很多的错误可能发生,真的发生了。解决该问题的关键是处理任何不可预见的(或可预见的错误)来控制用户的体验。随着Javascript使用,有各种各样的技术和语言特点,能正确解决任何问题。

处理Javascript中的错误是很危险的。如果你相信Murphy定律,最后会出错的!在这篇文章中,我将研究Javascript中的错误处理。我将涉及一些陷阱和良好的实践。最后,我们将讨论异步代码处理和Ajax。

我认为,事件驱动模型的Javascript增加了很多对语言意义。我认为这是事件驱动引擎的浏览器和错误报告机制没有区别。当错误发生时,它是相当于在一个时间点抛出事件。在理论上,我们可以处理Javascript像普通的事件错误的事件。如果对你来说很奇怪,学习以下旅程的重点。本文仅用于客户端的Javascript。

实例

本文中使用的示例代码都可以在GitHub上,与当前的页面看起来像这样:

单击每个按钮会引起误差。它模拟了一个异常TypeError类型。以下是定义和这样一个模块单元测试。

函数错误(){
var { };
返回foo.bar();
}
首先,这个函数定义了一个空对象。注意,在任何地方都没有定义bar()方法。我们使用单元测试来验证它是否导致了错误报告。

它('throws TypeError功能(){()
should.throws(目标、TypeError);
});
本单元测试使用测试断言在咖啡和should.js图书馆。Mocha是一个运行的测试框架,并should.js是断言库。如果你不熟悉它,你可以浏览自己的文件免费在线。测试用例通常开始与它('description)与通过或失败的断言在末端。使用该框架的优点是,你可以在节点做单元测试,而不是在浏览器中。我建议你做这些测试,因为它们中的许多严重验证Javascript的关键的基本概念。

如上所示,错误()定义了一个空对象,然后尝试调用该方法。因为在这个对象中没有bar()方法,它抛出一个异常。相信我,任何人都可以在动态语言中犯这样的错误,比如Javascript。

一个坏的示范

首先看看错误处理的错误方式。我抽象出错误的动作并将其绑定到按钮:

功能badhandler(FN){
{试
返回FN();
} catch(e){ }
返回null;
}
这个处理函数接收一个回调函数FN作为一个依赖项,然后在处理器内部调用这个函数。

它('returns值没有错误,函数(){())
函数(){()
返回1;
};
var结果=目标(FN);
(1)result.should.equal;
});

它('returns零错误,函数(){())
函数(){()
把误差(随机误差);
};
var结果=目标(FN);
应该(结果)相等(空);
});
如您所见,如果出现错误,这个奇怪的过程将返回null。回调函数FN()指向一个合法的方法或错误。

函数(处理程序,炸弹){
无功badbutton = document.getelementbyid(坏的);

如果(badbutton){
BadButton.addEventListener(听到咔哒声,函数(){(){
汉德勒(炸弹);
console.log(想象,升职的隐藏错误);
});
}
}(badhandler,错误));
糟糕的是,我就有空。这让我很困惑的时候,我想确定什么是错的。这个错误决策,沉默策略涵盖的每一个环节都从用户体验设计数据损坏。令人沮丧的一面是,我不得不花时间调试,但我不在try-catch代码看到错误。这个奇怪的处理隐藏在代码中的所有错误,并且认为一切都是正常的。这可以顺利的开展一些团队不注重代码质量。然而,这些隐藏的错误最终会迫使你花几个小时在调试代码。多层解决方案依赖于调用堆栈,以确定它是可能的错误是从哪里来的。这是可能的,沉默的在少数情况下,尝试捕获可能是适当的,但如果错误的话,处理它不是一个好的计划。

这次失败,沉默策略,会让你更好地处理你的code.javascript误差提供了一个更优雅的方式来处理这样的问题。

不可读的格式

继续,看看你不太明白的方法。我将跳过DOM中紧密耦合的部分。这一部分与我们刚才看到的糟糕的处理没有什么不同。重点是在下面的单元测试中处理异常的部分。

功能uglyhandler(FN){
{试
返回FN();
} catch(e){
把错误(新的错误);
}
}

它('returns新的误差与误差、函数(){)
函数(){()
把新的TypeError(错误);
};
should.throws(函数(){()
目标(FN);
},错误);
});
有处理它只是坏的方式很好的改善,异常抛出在调用栈。我喜欢的地方是,错误是脱离栈,这对调试有很大的帮助。当异常被抛出时,解释器会在水平的调用堆栈的层面寻找接下来的处理功能,这提供了很多机会在调用堆栈的顶层处理错误。不幸的是,因为他是一个被误解的错误,我看不到原来的错误信息。所以我要寻找过去的调用堆栈,找到最原始的例外。但在至少我知道有一个错误在异常抛出。

这不可读的错误处理,虽然无害,使代码难以理解。让我们看看浏览器如何处理错误。

调用堆栈

然后抛出异常的一种方法是添加尝试…在调用堆栈顶部的catch代码块。例如 uff1a

函数主(炸弹){
{试
炸弹();
} catch(e){
所有的错误处理
}
}
但请记住,我说过浏览器是事件驱动的是的,一个Javascript中的例外,无非是一个事件。解释器停止程序异常的当前上下文和抛出一个异常。为了证实这一点,下面是一个全球性的事件处理函数的误差,我们可以看到,它看起来像这样:

Window.addEventListener(错误,函数(e){
VaR误差= e.error;
console.log(错误);
});
这个事件处理函数的执行环境中捕获错误。错误的事件可以做出各种各种的地方错误。这种方法的重点是集中处理代码中的错误。像任何其他的事件,你可以使用一个全局的处理函数来处理各种不同的错误。这使得错误处理一个单一的目标,如果你符合固体(单一职责单一职责、开闭开闭,Liskov替代,接口隔离原则分离依赖依赖倒置)原则。你可以在任何时间登记功能错误处理。解释器循环通过这些功能,代码是从报表全解放尝试…这种方法的关键是处理诸如处理Javascript普通事件之类的错误。

现在,有一种方法来显示调用堆栈的全局处理函数,我们可以用它做什么,我们想使用调用堆栈。

记录下调栈

调用堆栈在处理bug的过程中非常有用。好消息是浏览器提供了这个信息。即使是现在,错误对象的堆栈属性不是标准的,但它在相对较新的浏览器中得到了普遍支持

所以我们能做的最酷的事情就是把它打印服务器上:

Window.addEventListener(错误,函数(e){
var = e.error.stack堆栈;
VaR的消息= e.error.tostring();
如果(堆栈){
消息=+堆栈;
}
Var XHR = new XMLHttpRequest ();
Xhr.open('post ',' /日志,真的);
Xhr.send(消息);
});
在代码示例中可能并不明显,但事件处理程序是由前面的错误代码触发的,如上所述,每个处理器都有一个目的,这使得代码变干(不要重复自己在创建轮子时没有重复),我感兴趣的是如何在服务器上捕获这些消息。

下面是节点运行时的屏幕截图

调用堆栈有助于调试代码。永远不要低估调用堆栈的作用

异步处理

那么,处理异步代码是相当危险的!Javascript将异步代码从当前的执行环境中引入…catch语句有问题。

功能asynchandler(FN){
{试
setTimeout(){()函数(
(FN);
},1);
} catch(e){ }
}
单元测试有剩余部分:

它('不捕获异常和错误,函数(){)
函数(){()
把新的TypeError(错误);
};
FailedPromise(function(){()
目标(FN);
Should.be.rejectedWith(TypeError)});
});

功能failedpromise(FN){
返回新的承诺(函数(解析,拒绝){
拒绝(FN);
});
}
我必须以验证异常的方式结束这个处理程序。请注意,尽管我的代码正在试用中…还有一些未处理的异常…catch只在单个执行环境中工作。当抛出异常时,解释器的执行环境不是当前的catch catch块。这种行为的发生与Ajax调用类似。所以现在有两个选项。一个选项是捕获异步回调中的异常:

setTimeout(){()函数(
{试
(FN);
} catch(e){
这种异步错误 / /处理
}
},1);
这个方法很有用,但还有很大的提升空间…catch代码块到处出现在代码中。事实上,编程调用在上世纪70年代,他们希望他们的代码。此外,V8引擎不鼓励尝试使用功能。catch代码块(V8是Chrome浏览器和使用节点的Javascript引擎)。他们建议该代码块捕获异常是写在调用堆栈的顶层。

因此,这告诉了我上面所说的,在任何上下文中都必须有一个全局错误处理程序。干固原理不太好。全局错误处理程序可以保持代码的可读性和干净性。

下面是服务器端异常处理打印的报告。请注意,如果您使用示例中的代码,输出的内容可能会因使用的浏览器不同而略有不同。

这个处理函数甚至可以告诉我哪些错误是从异步代码。它告诉我,误差来源于setTimeout()处理功能。这很酷!

错误是每个应用程序的一部分,但适当的错误处理是不行的。至少有两种方法来处理错误。一个是计划的失败,是无声的,即忽略代码中的错误,及时发现和解决错误的方法,那就是停止在错误的地方繁殖。我想我已经很清楚,为什么我同意。我的选择:不要隐藏问题。没有人会怪你在你的程序中的意外。这是可以接受的,中断点,重现,给用户的一种尝试。在一个不完美的世界,这是给自己一个机会重要。错误是不可避免的,而你要做的是解决错误重要。Javascript的错误处理功能的合理利用和自动和灵活的解码可以让用户体验更流畅,同时,使诊断工作更容易为开发人员。
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部