前言最近在公司的Koa.js项目中遇到了一个问题。我使用thrift库创建连接,在接口中使用已连接的客户端发送请求。结果抛出错误,连接失败,程序中断。执行,错误无法用try/catch捕获。然后我查看了创建连接的源代码,在Connection构造函数中发现了如下代码:varConnection=exports.Connection=function(stream,options){varself=this;EventEmitter.call(这个);this.connection=流;//...其他代码this.connection.addListener("error",function(err){//只有在没有其他人在监听连接时才会发出错误//或者如果有人在监听我们,因为Node将未处理的//'error'事件转换为异常。if(self.connection.listeners('error').length===1||self.listeners('error').length>0){self.emit("错误”,错误);}});//...othercode}注意翻译:只有当没有人正在监听连接或有人正在监听我们(this)时才会发出错误,因为Node将未处理的“错误”事件变为异常。节点错误处理同步API除了少数例外,同步API(任何不接受回调函数的阻塞方法,例如fs.readFileSync)使用throw来报告错误。任何使用JavaScript抛出机制都会引发异常,必须使用try...catch处理,否则Node.js进程将立即退出。try{thrownewError('somethingerror');}catch(e){//处理错误}异步API当你使用try/catch来尝试捕获异步操作中的错误时,你会发现你无法捕获它们try{setTimeout(()=>{thrownewError('somethingerror');},1000);}catch(e){console.log(e);}//执行结果//UncaughtError:somethingerror//at:3:11异步API中发生的错误可以通过多种方式报告:大多数接受回调函数的异步方法将接受传递给该函数的错误对象作为第一个参数。如果第一个参数不为null并且是Error的实例,则发生了应该处理的错误。constfs=require('node:fs');fs.readFile('一个不存在的文件',(err,data)=>{if(err){console.error('读取文件时出错!',err);return;}//否则处理数据});在EventEmitter对象上调用异步方法时,错误可以路由到对象的“错误”事件。constnet=require('node:net');constconnection=net.connect('localhost');//添加一个'error'事件处理器到流中:connection.on('error',(err)=>{//如果连接被服务器重置,//或者根本无法连接,或者如果连接遇到任何类型的错误,//错误将发送到这里。console.error(err);});connection.pipe(process.stdout);Node.jsAPI中的一些典型异步方法可能仍然使用抛出机制来引发必须使用try...catch处理的异常。注意:使用async/await处理异步函数时,应该使用同步函数的try/catch进行处理。对于所有的EventEmitter对象,如果没有提供'error'事件处理程序,将抛出错误,导致Node.js进程报告未捕获的异常并崩溃,除非:领域模块被正确使用或已为该事件注册了处理程序'uncaughtException'事件。EventEmitterEventEmitter是Node.js内置的事件模块提供的类。它的核心是对事件触发和事件监听函数的封装。通过require("events");访问模块:const{EventEmitter}=require('event');让eventEmitter=newEventEmitter();提供以下方法:addListener(event,listener)将指定事件的侦听器添加到侦听器数组的末尾。on(event,listener)为指定事件注册一个监听器,接受一个字符串事件和一个回调函数。once(event,listener)为指定事件注册一个一次性的监听器,即最多只会触发一次监听器,触发后立即释放监听器。removeListener(event,listener)移除一个指定事件的监听器,该监听器必须是该事件的注册监听器。它接受两个参数,第一个是事件名称,第二个是回调函数名称。removeAllListeners([event])删除所有事件的所有侦听器,或者如果指定了事件,则删除指定事件的所有侦听器。setMaxListeners(n)默认情况下,如果您添加超过10个侦听器,EventEmitters将输出警告消息。setMaxListeners函数用于更改监听器的默认限制数量。listeners(event)返回指定事件的侦听器数组。emit(event,[arg1],[arg2],[...])按照监听器的顺序执行每个监听器,如果事件有注册监听器则返回true,否则返回false。问题原因及解决方法由于没有在连接中添加额外的错误监控,self.emit("error",err);会执行,但是没有对应的监听器,导致未捕获异常,导致节点中断执行。因此,只需要在createConnection创建的对象上监听error事件即可。参考:关于前端错误处理的错误传播与拦截