Node.js——异常处理

异常处理

1、使用throw关键字抛出异常

throw关键字用于抛出一个异常,它可以在特定的情形下自行抛出异常。throw语句的基本格式如下:

js 复制代码
throw value

参数value表示抛出的异常,它的值可以是任何JavaScript类型的值(包括字符串、数字或对象等)​。例如,在JavaScript代码中使用下面代码抛出不同类型的异常都是合法的:

js 复制代码
throw "程序出错了";  //抛出了一个值为字符串的异常
throw 1;             //抛出了一个值为整数1的异常
throw true;          //抛出了一个值为true的异常

但在Node.js中,通常不抛出这些类型的值,而是抛出Error对象,例如下面的代码:

js 复制代码
throw new Error('程序出错了')

2、Error错误对象

Error对象是一个错误对象,它由Error核心模块提供,当使用Error对象时,并不表明错误发生的具体情况,它会捕获堆栈跟踪,并提供所发生错误的描述内容。Error对象的使用方法如下:

js 复制代码
new Error(message)

参数message表示要显示的错误信息。

Error对象提供了一些属性,用于获取错误相关的信息,分别如下。

  • name属性:获取错误的类型名称,比如内置错误类型TypeError等。
  • message属性:获取错误信息。
  • stack属性:获取代码中Error被实例化的位置。

Error类是Node.js中所有错误类的基类,其常用子类及说明如表所示。

Error类的子类 说明
AssertionError 断言错误
RangeError 表明提供的参数不在函数的可接受值的集合或范围内,无论是数字范围,还是给定的函数参数选项的集合
ReferenceError 表明试图访问一个未定义的变量,此类错误通常表明代码有拼写错误或程序已损坏
SyntaxError 表明程序不是有效的JavaScript,.这些错误可能仅在代码评估的结果中产生和传播
SystemError 表明Nod©.js在运行时环境中发生异常时会生成系统错误,这通常发生在应用程序违反操作系统约束时,例如,如果应用程序试图读取不存在的文件,则会发生系统错误

例如,下面代码定义了一个代码块,其中通过实例化Error对象创建了一个异常,并使用throw关键字抛出该异常:

js 复制代码
let syncError = ()=>{
	throw new Error('自定义异常');
}

3、使用try...catch语句捕获异常

异常定义之后,需要在程序中捕获,这时需要使用try...catch语句。try...catch语句允许在try后面的大括号{}中放置可能发生异常情况的程序代码,以对这些代码进行监控;在catch后面的大括号{}中放置处理异常的程序代码。try...catch语句的基本语法如下:

js 复制代码
try {
               //可能会出错的代码,出错时抛出一个错误
} catch (e) {
               //处理异常的代码
}

参数e表示捕获的异常。

例如,下面代码使用try...catch捕获17.3.2节示例代码中抛出的异常信息:

js 复制代码
try {
     syncError()
} catch (e) {
     console.log(e.message)
}
console.log('异常被捕获')

程序运行如下:

复制代码
自定义异常
异常被捕获

在开发程序时,如果遇到需要处理多种异常信息的情况,可以在一个try代码块后面跟多个catch代码块,这里需要注意的是,如果使用了多个catch代码块,则catch代码块中的异常类顺序是先子类后父类。

完整的异常处理语句应该包含finally代码块,通常情况下,无论程序中有无异常产生,finally代码块中的代码都会被执行,其语法格式如下:

js 复制代码
try{
            //可能会出错的代码,出错时抛出一个错误
}catch(e){
            //处理异常的代码
}finally{
            //最终执行的代码
}

使用try...catch...finally语句时,不管try代码块内有没有抛出异常,finally代码块总会被执行。如果try代码块内发生错误,finally代码块将在catch代码块之后被执行;如果没有发生错误,将跳过catch代码块,直接执行finally代码块中的代码。

使用异常处理语句时,可以不写catch代码块,比如写成try...finally的形式,但需要注意的是,try代码块后必须至少跟一个catch或finally代码块,不能只写try。

例如,使用同步方式读取一个文件,并使用try...catch语句捕获文件不存在错误,最后在finally代码块内输出"执行完毕"的提示,代码如下:

js 复制代码
const fs=require("fs")
try{
     var data = fs.readFileSync("test.txt", {"encoding":"utf8"})
} catch (err) {
     console.log("文件不存在")
     throw err;
} finally {
     console.log("执行完毕!")
}

运行结果如下:

js 复制代码
文件不存在
执行完毕!
ENOENT: no such file or directory, open 'test.txt'

4、异步程序中的异常处理

如果是异步程序出现异常,该如何捕获呢?例如,下面是一个异步代码块,其中抛出了一个异常,代码如下:

js 复制代码
//模拟异步代码块内出现异常
let asyncError = () => {
     setTimeout(function () {
          throw new Error('异步异常')
     }, 100)
}

如果我们使用传统的try...catch捕获上面异步代码中抛出的异常,则写法应该如下:

js 复制代码
(async function () {
     try {
          await asyncError()
     } catch (e) {
          console.log(e.message)  //处理异常
     }
})()

但在运行程序时,却出现了如图所示的结果。

通过上面示例代码可以看出,异步代码中的异常是无法使用try...catch方法捕获的,那么,如何捕获异步程序中的异常呢?Node.js中提供了两种方法,用于捕获异步程序中的异常,分别如下。

  • process方式。process模块是Node.js提供给开发者用来和当前进程进行交互的工具,通过监听它的uncaughtException事件,可以处理所有未被捕获的异常,包括同步代码块中的异常和异步代码块中的异常。例如,下面代码用来捕获本节开始定义的异步代码中的异常:
js 复制代码
process.on('uncaughtException', function (e) {
     console.log(e.message)                     //处理异常
});
asyncError()
  • domain方式。通过监听domain模块的error事件来处理异步代码块中的异常,domain模块主要用来简化异步代码的异常处理,它可以处理try...catch无法捕捉的异常。例如,下面代码使用domain方式捕获本节前面定义的异步代码中的异常:
js 复制代码
let domain = require('domain')
let d = domain.create()
d.on('error', function (e) {
     console.log(e.message)     //处理异常
})
d.run(asyncError)

使用process方式和domain方式都可以捕获异步代码块中的异常,但process方式只适用于记录异常信息的场合,因此,在捕获异步代码库中的异常时,推荐使用domain方式。

相关推荐
FreeBuf_4 小时前
谷歌将Axios npm供应链攻击归因于朝鲜APT组织UNC1069
前端·npm·node.js
阿正的梦工坊4 小时前
pnpm和npm前端包管理工具有什么不同?
前端·npm·node.js
叶半欲缺4 小时前
Node.js 安装教程
node.js
吴声子夜歌4 小时前
Node.js——Web模板引擎
前端·node.js
雪碧聊技术5 小时前
linux下载node.js(这里面已经包含了npm)
npm·node.js
摇滚侠16 小时前
搭建前端开发环境 安装 nodejs 设置淘宝镜像 最简化最标准版本 不使用 NVM NVM 高版本无法安装低版本 nodejs
java·开发语言·node.js
tumeng07111 天前
Node.JS 版本管理工具 Fnm 安装及配置(Windows)
windows·node.js
xrkhy1 天前
MacOS M3 安装nvm以及node.js
macos·node.js
xiaohe071 天前
Node.js NativeAddon 构建工具:node-gyp 安装与配置完全指南
node.js