手机版

JavaScript中错误的正确处理总结 你用对了吗

时间:2021-09-03 来源:互联网 编辑:宝哥软件园 浏览:

JavaScript的事件驱动范式不仅增加了丰富的语言,还使JavaScript编程更加多样化。如果浏览器被认为是JavaScript的事件驱动工具,那么当错误发生时,就会引发一个事件。理论上,这些错误只是JavaScript中的简单事件。

本文将讨论客户端JavaScript中的错误处理。本文主要介绍了JavaScript中的易错性、错误处理和异步代码编写。

让我们来看看如何正确处理JavaScript中的错误。

演示演示

本文中使用的演示可以在GitHub上找到。运行后,会是这样的页面:

每个按钮将抛出一个“异常”,这个错误将模拟抛出的异常类型错误。以下是模块的定义:

//scripts/error . jsfunction error(){ var foo={ };return foo . bar();}首先,这个函数声明了一个空对象foo。请注意,bar()没有在任何地方定义。接下来,验证该单元测试是否会导致“错误”:

//tests/scripts/errorTest.jsit('抛出一个TypeError ',function(){ short . throws(error,TypeError));});单元测试在Mocha中,并且在Should.js中有一个测试语句.Mocha是测试运行工具,Should.js是断言库。该单元测试在节点上运行,不使用浏览器。

错误()定义了一个空对象,然后尝试访问一个方法。因为bar()在对象中不存在,所以引发异常。这种错误发生在像JavaScript这样的动态语言中,每个人都可能遇到!

错误处理(一)

使用以下代码处理上述错误:

//scripts/BadHandler . jsfunction BadHandler(fn){ try { return fn();} catch (e) { }返回null}处理程序将fn作为输入参数,然后在处理程序函数内部调用fn。单元测试将反映上述错误处理程序:

//tests/scripts/baddhandlertest . jsit('返回一个没有错误的值',function(){ var fn=function(){ return 1;};var结果=BadHandler(fn);result . short . equal(1);});它('返回一个有错误的null ',function() { var fn=function() {抛出新的Error('随机错误');};var结果=BadHandler(fn);应该(结果)。等于(空);});如果出现问题,错误处理程序将返回null。fn()回调函数可以指向合法的方法或错误。

将继续处理以下点击事件:

//scripts/baddhandlerdom . js(function(handler,bomb){ var baddbutton=document . getelementbyid(' bad ');if(BadButton){ BadButton . AddEventListener(' click '),function(){ handler(bomb);console . log(‘想象一下,因为隐藏错误而被提升’);});}}(badHandler,错误));这种处理方法在代码中隐藏了一个很难发现的错误。隐藏的错误可能需要几个小时来调试。特别是在具有深度调用栈的多层解决方案中,这个错误将更难发现。所以这是一个非常糟糕的处理错误的方法。

错误处理(2)

下面是另一种错误处理方法。

//scripts/uglyHandler . jsfunction uglyHandler(fn){ try { return fn();} catch (e) {抛出新错误('新错误');}}处理异常的方式如下:

//tests/scripts/uglyhandlertest . jsit('返回带有错误的新错误',function(){ var fn=function(){ throw new type error(' type error ');};short . throws(function(){ uglyHandler(fn);},错误);});以上明显改进了错误处理程序。这里异常调用堆栈进行冒泡。同时错误会展开栈,对调试很有帮助。除了抛出异常之外,解释器还会沿着堆栈寻找额外的处理。这也带来了从栈顶处理错误的可能性。但这仍然是一个糟糕的错误处理,需要我们从堆栈中一步一步地跟踪原始异常。

可以采用一种替代方法,通过自定义错误方法来结束这种糟糕的错误处理。当您在错误中添加更多细节时,这将使该方法非常有帮助。

例如:

//脚本/specific error . js//创建自定义errorvar SpecifiedError=函数specific error(消息){ this.name=' SpecifiedErrorthis.message=message | |this.stack=(新的Error())。堆栈;};指定错误。原型=新错误();指定错误。原型。构造函数=指定错误;//scripts/uglyHandlerImproved . jsfunction uglyHandlerImproved(fn){ try { return fn();} catch(e){ throw new specified error(e . message);} }//tests/scripts/uglyhandlerimprovedtest . jsit('返回带有错误的指定错误',function () { var fn=function () {抛出新的type error(' type error ');};short . throws(function(){ uglyHandlerImproved(fn);},指定错误);});指定的错误添加了更多详细信息,并保留了原始错误消息。有了这个改进,上面的处理就不再是一个糟糕的方式,而是一个清晰有用的方式。

在上述处理之后,我们还收到了一个未处理的异常。接下来,让我们看看浏览器在处理错误时有多大帮助。

扩展堆栈

处理异常的一种方法是添加try.在调用堆栈的顶部捕获。

例如:

函数main(bomb){ try { bomb();} catch(e){//处理所有错误的事情}}但是,浏览器是事件驱动的,JavaScript中的异常也是事件。当异常发生时,解释器暂停执行并展开:

//scripts/error handlerdom . jswindow . addeventlistener(' error ',function(e){ var error=e . error;console.log(错误);});此事件处理程序捕获任何执行上下文中出现的错误。每个目标中发生的错误事件会触发各种类型的错误。这种集中在代码中的错误处理非常激进。您可以使用菊花链处理来处理特定的错误。如果遵循SOLID原则,可以采用单一用途的错误处理方法。这些处理程序可以随时注册,解释器会循环执行需要的处理程序。代码库可以从尝试中释放.catch块,这也使调试变得容易。在JavaScript中,将错误处理视为一个事件是很重要的。

捕获堆栈

解决问题时,调用栈可能非常有用,浏览器可以提供这些信息。尽管堆栈属性不是标准的一部分,但最新的浏览器已经可以查看这些信息。

以下是在服务器上记录错误的示例:

//scripts/erraojaxhandlerdom . jswindow . addeventlistener(' error ',function(e){ var stack=e . error . stack;var message=e . error . ToString();if(stack){ message=' \ n ' stack;} var xhr=new XMlhttprequest();xhr.open('POST ','/log ',true);//激发一个带有错误详细信息的Ajax请求xhr.send(消息);});每个错误处理都有一个单一的目的,可以保持代码的DRY原则(单一目的,不要重复自己的原则)。

在浏览器中,您需要向DOM添加事件处理。这意味着,如果您正在构建第三方库,您的事件将与客户端代码共存。Window.addEventListener()将帮助您在不擦除现有事件的情况下处理它。

这是服务器上的日志截图:

您可以从命令提示符查看日志,但是在Windows上,日志不是动态的。

通过日志,我们可以清楚地看到哪些具体情况触发了哪些错误。调试时调用栈也非常有用,所以不要低估调用栈的作用。

在JavaScript中,错误消息只适用于单个域。因为当使用来自不同域的脚本时,您将看不到任何错误详细信息。

一种解决方案是在保留错误消息的同时重新抛出错误:

一旦错误备份重新启动

尝试{ return fn();}捕获(e) {抛出新的错误(e . message);},全局错误处理程序将完成剩下的工作。确保您的错误处理在同一个域中,这将保留原始消息、堆栈和自定义错误对象。

异步处理

当JavaScript运行异步代码时,以下异常处理将导致问题:

//scripts/async handler . jsfunction async handler(fn){ try {//这从当前上下文setTimeout(function () { fn())中撕开了潜在的炸弹;}, 1);} catch (e) {}}通过单元测试检查问题:

//tests/scripts/asynchrandlertest . jsit('不捕捉有错误的异常',function(){//The bomb var fn=function(){抛出新的type error(' type error ');};//检查异常没有被捕获应该. do notthrow(function(){ asynchrandler(fn);});});这个异常没有被捕获,我们通过单元测试进行了验证。虽然代码包含try.抓住机会,试试看.catch语句只能在单个执行上下文中工作。当抛出异常时,解释器已经从try中逃脱.catch,所以不处理异常。同样的情况也会发生在Ajax调用上。

因此,一种解决方案是在异步回调中捕获异常:

setTimeout(function(){ try { fn();} catch (e) { //处理此异步错误}},1);这种方法会更有效,但仍有很大的改进空间。

首先,这些尝试.整个区域都陷入了陷阱。实际上,V8浏览器引擎不鼓励使用try.函数中的catch块。V8是Chrome浏览器和Node中使用的JavaScript引擎。一种方法是尝试移动.catch块移动到调用堆栈的顶部,但这不适合异步代码编程。

由于全局错误处理可以在任何上下文中执行,如果添加了窗口对象进行错误处理,就可以保证代码的DRY和SOLID原则。同时,全局错误处理可以确保您的异步代码是干净的。

以下是服务器上异常处理的报告内容。请注意,输出会因浏览器而异。

从错误处理可以看出,错误来自异步代码的setTimeout()函数。

结论

在处理错误的时候,我们不应该隐藏问题,而应该及时发现问题,用各种方法追溯问题的根源,以解决问题。虽然编写代码时不可避免地会埋下错误,但我们不必为错误感到太羞愧。这正是我们现在需要做的,及时解决和发现问题,以避免更大的问题。

摘要

以上是边肖介绍的JavaScript中错误正确处理的总结,希望对大家有所帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!

版权声明:JavaScript中错误的正确处理总结 你用对了吗是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。