前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Node.js req res error 事件 漏监听后果
NoNode.js服务端工程

Node.js 中为什么请求处理时 req 与 res 上的 error 事件都要监听,漏掉会怎样?

req与res是流对象,流在emit('error')且没有监听器时会抛出错误并令Node进程崩溃;两路错误来源不同,必须各自监听,漏一路就有一路崩溃风险。

前端进阶之旅 · 一题精讲更新于 2026.09.05
Node.js#服务端工程#安全#HTTP#并发编程
先看核心答案
理解线索

流错误与崩溃机制

  1. 流未附加监听emit('error')时无监听器会直接抛出。
  2. 导致进程崩溃抛出的异常未被捕获默认终止进程。
  3. 两路来源不同请求读取与响应写入都可能发生错误。

只监听一个,另一个出错仍会崩溃。

核心回答

先记住这个答案

req(IncomingMessage)是Readable流,res(ServerResponse)是Writable流。当底层连接异常中断或写入失败,流会emit('error')。若没有监听器,该事件会作为未处理的错误被抛出到事件循环,进程默认打印堆栈后退出。req的错误多来自客户端断开或解析异常,res的错误多来自对端关闭后继续写入。只监听其中一个,另一个出错时依旧崩溃。故应同时为req和res绑定error处理程序,并在回调中清理资源与互相终止,确保单个请求错误不拖垮整个进程。

  • req和res是流,未监听error会抛出导致崩溃
  • req错误来自接收中断,res错误来自写入失败
  • 必须分别监听并处理,才能保证服务稳定

为什么'error'事件必须处理?

Node.js的HTTP请求对象req(IncomingMessage)和响应对象res(ServerResponse)分别是可读流和可写流。流在内部发生异常时会发出'error'事件。如果该事件没有挂任何监听器,Node就像对待普通EventEmitter一样,会将错误作为未捕获异常在事件循环中抛出。这个异常不会被后续的Promise.catch或try/catch逮住,进程只能打印堆栈并退出。

req和res的错误源截然不同:req可能因客户端提前断开、报文解析失败或内容编码问题报错;res则可能在底层socket已关闭后仍尝试写入数据、或由于write超时被置错。业务代码若只监听请求的'aborted'事件或用try包裹async路由,往往无法覆盖这些流级错误,所以必须直接为每个流挂error处理器。

上传中断场景中的两个崩溃点

假设服务接收POST大文件,用req.on('data')收集字节,客户端传到一半突然断网,TCP层会通知本端连接异常。该req流随即触发'error';如果代码没有监听req的error,进程会立刻退出,殃及正在处理的其它请求。更隐蔽的是,因为底层socket已失效,本服务向res写入返回体也会触发另一个'error'——即使req的error被提前处理,res上漏监听依然会让进程崩溃。

可靠处理是:在请求刚开始就同时挂req.on('error', handleError)和res.on('error', handleError),handleError里记录错因并做清理:如clearTimeout、删除临时文件,然后调用req.destroy()或res.destroy()关闭对方。还要避免在错误回调里再次触发可能失败的IO操作。经这样防护后,单个客户端异常只会作废当前请求,不能影响同进程的其他请求。

哪些情况仍会漏掉或冲突?

第一种常见失效是:把req或res交给框架或封装函数(如stream.pipeline、finished)时,工具库已接管了错误,此时若再在外部额外监听,虽然不至于冲突,但不保证能回调到自己的监听——因为流的error可能已被内部消费。真正会漏的是自己用.on('data')、.write或.pipe的裸流代码,只要没手动绑error,错误就会向上穿透。

第二种误区是:在某个时机过早移除监听,或只在第一次error后清理就认为安全。要记住error事件可能在不同时点出现,只要请求未结束,监听应保持有效。实现上可以在开始传输前绑定,在req/res任一触发'close'后再设标志位,后续事件直接忽略。代价是每个请求多两个闭包与一个清理函数,换取的是明确失败边界和进程存活保障。

回答前,多想一步

容易答错的地方

只监听res的error即可
会漏掉req侧错误。req是独立可读流,其解析、接收失败会emit('error'),不监听同样导致未处理异常。例如客户端在body未读完就RST时,req会先error,若漏监听则进程崩溃。
在error回调里再调用res.end兜底
res可能已经销毁,end()会再触发一次error或抛异常。应该在回调里先判断writable,再用destroy或直接销毁socket,同时避免重复调用。记录日志后及时清理资源才是重点。
试着用自己的话回答

面试官还会怎么问?

使用stream.pipeline()后还需要手动监听req和res的error吗?

pipeline()会把所有流的错误汇总到其回调中,并自动销毁相关流。若提供了非空回调,错误不会成为未处理异常,但管道完成前还可能自行触发error,建议仍挂载并只做日志和资源清理。

'error'事件与'aborted'事件在HTTP请求上的区别是什么?

'aborted'只表示客户端中止请求,不一定会触发'error';但一些底层TCP错误会同时导致'aborted'与'error'。Node.js流规范要求只有无监听时error才会抛异常,'aborted'没有这个特性。判断中止仍需两者结合。

错误发生时应该调用res.end()还是socket.destroy()?

推荐先检查socket状态,用req.destroy()或res.destroy()直接切断底层连接,因为end()需要排队写结束帧,在已损坏连接上会立即失败或卡死。同时注意不要重复销毁,销毁后所有后续写操作应被忽略。

从一道题,走向一组知识

把知识连起来

服务端工程

Node.js 进程中 SIGINT、SIGTERM、SIGHUP、SIGKILL 的默认行为分别是什么,哪些不能被捕获?

同属「服务端工程」专题,接着看 Node.js process signal SIGINT SIGTERM 默认行为 在具体场景中的处理方式。

进程与线程

spawnSync、execSync 在 Node.js 中什么场景适合使用?

继续了解 child_process spawnSync 阻塞 场景,补充本题涉及的 Node.js 相关知识。

参考资料

  • Stream | Node.js v26.8.1 Documentation

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 为什么'error'事件必须处理?
  3. 上传中断场景中的两个崩溃点
  4. 哪些情况仍会漏掉或冲突?
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑