JavaScript里的错误捕获和处理

776 阅读4分钟

「这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

不管你多么精通编程,有时我们的脚本总还是会出现错误。可能是因为编写出错,或是与预期不同的用户输入,或是错误的服务端响应以及其他数千种原因。

通常,如果发生错误,脚本就会“死亡”(立即停止),如果你不希望脚本直接停止,那么你可以使用 try..catch,来进行错误的“捕获(catch)”。

try..catch语法

try..catch 结构由两部分组成:trycatch

try {
  // 代码...
} catch (err) {
  // 错误捕获
}

💡 执行步骤

  • 先执行try {...} 中的代码
  • 没有错误,忽略 catch(err):执行到 try 的末尾并跳过 catch 继续执行。
  • 出现错误,执行停止 try ,控制流转向 catch(err) 的开头。变量 err(我们可以使用任何名称)将包含一个 error 对象,该对象包含了所发生事件的详细信息。

image-20211120202742476

所以try {…} 块内的错误不会让脚本停止,并且你还可以在 catch 中处理这个错误。

try..catch失效的情况

代码本身就不可执行

try..catch 只对有效的 JavaScript 代码有用,什么意思呢?

🎨 如下示例

  • 如果是变量未定义的错误,可以被捕获到;
  • 但是如果是像这种多写了一个【花括号】的语法错误,并不能正常运行。

image-20211120203551009

非同步工作

如果在“计划的(scheduled)”代码中发生异常,例如在 setTimeout 中,则 try..catch 不会捕获到异常:

🎨 示例

可以看到以下示例运行结果中,未定义的变量错误没有被捕获到,而是直接报错了。这是因为try..catch 包裹了计划要执行的函数,该函数本身要稍后才执行,这时引擎已经离开了 try..catch 结构。

image-20211120204141366

💡 改进

如果你想捕获到计划的(scheduled)函数中的异常,那么 try..catch 必须在这个函数内

image-20211120204431846

catch里的Error对象

发生错误时,JavaScript 生成一个包含有关其详细信息的对象。然后将该对象作为参数传递给 catch

image-20211120205035746

catch里的error 对象具有两个主要属性:

  • name Error 名称。例如,对于一个未定义的变量,名称是 "ReferenceError"
  • message 关于 error 的详细文字描述。

还有其他非标准的属性在大多数环境中可用。其中被最广泛使用和支持的是:

  • stack 当前的调用栈:用于调试目的的一个字符串,其中包含有关导致 error 的嵌套调用序列的信息。

throw语句

throw语句用来抛出一个用户自定义的异常。当前函数的执行将被停止(throw之后的语句将不会执行),并且控制将被传递到调用堆栈中的第一个catch块。如果调用者函数中没有catch块,程序将会终止。

🎨 示例

image-20211120205652478

从技术上说,你可以将任何东西用作 error 对象。

throw "Error2"; // 抛出了一个值为字符串的异常
throw 42;       // 抛出了一个值为整数42的异常
throw true;     // 抛出了一个值为true的异常

但最好使用对象,最好使用具有 namemessage 属性的对象(某种程度上保持与内建 error 的兼容性)。

try...catch...finally

try..catch 结构可能还有一个代码子句(clause):finally

try {
   ... 尝试执行的代码 ...
} catch(e) {
   ... 处理 error ...
} finally {
   ... 总是会执行的代码 ...
}

finally 子句(clause)通常用在:当我们开始做某事的时候,希望无论出现什么情况都要完成完成某个任务。

try..finally

try..finally 结构也是可以正常执行的,当不想在这儿处理 error,但是需要确保启动的处理被完成时可以使用这个结构。

function func() {
  // 开始执行需要被完成的操作(比如测量)
  try {
    // ...
  } finally {
    // 完成前面我们需要完成的那件事儿,即使 try 中的执行失败了
  }
}

这段代码由于没有 catch,所以 try 中的 error 总是会使代码执行跳转至函数 func() 外。但是,在跳出之前需要执行 finally 中的代码。

参考资料:

MDN try...catch

Error handling


🎨【点赞】【关注】不迷路,更多前端干货等你解锁

往期推荐

👉 产品、技术、设计等各互联网领域的「基础术语」扫盲

👉 Web安全的防御手段都在这里了!

👉 JavaScript的7大类型补缺补漏!

👉 JavaScript深拷贝和浅拷贝看这篇就够了!