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方式。

相关推荐
无巧不成书02181 天前
2026最新Next-AI-Draw-io全攻略:AI驱动专业图表生成,Docker/Node.js本地部署零踩坑指南
人工智能·docker·node.js·next-ai-draw-io
悟空瞎说2 天前
我踩过的4个Node.js微服务经典Bug,用一个库彻底解决(2000字详解+可直接复用代码)
后端·node.js
捉鸭子2 天前
某红书X-s X-s-common VMP逆向(算法还原)
python·web安全·网络安全·node.js·网络爬虫
freewlt2 天前
Node.js 性能分析实战指南:从入门到精通
node.js
火乐暖阳851052 天前
Vue3+Node.js
vue.js·node.js·pnpm·koa2·myslq2
被巨款砸中2 天前
从零到一:构建高效 Node.js 后端 API (Koa + Prisma 实战)
前端·javascript·vue.js·node.js·web
网络点点滴2 天前
Node.js-填充模板
node.js
zhensherlock2 天前
Protocol Launcher 系列:Trello 看板管理的协议自动化
前端·javascript·typescript·node.js·自动化·github·js
iNgs IMAC2 天前
如何在Windows系统上安装和配置Node.js及Node版本管理器(nvm)
windows·node.js
ZJY1322 天前
3-12:路由和重构
后端·node.js