Node.js触发未处理error事件 报ERR_STREAM_WRITE_AFTER_END错误原因求解
错误根因
Node.js的ServerResponse属于可写流实例,一旦调用res.end()方法,代表本次响应的流已经完全结束、关闭,此时如果再对该实例调用res.write()或者再次调用res.end(),就会触发ERR_STREAM_WRITE_AFTER_END报错。
对照你的代码,触发逻辑非常明确:
你写的三个响应分支是非互斥的独立判断,没有任何中断后续执行的逻辑:
- 当请求路径为
/时,第一个if命中,执行res.end('Welcome to our home page'),此时响应已经被标记为结束 - 代码不会因为前面执行过end就自动停止运行,会继续走完所有同步逻辑:第二个
if判断不通过,最后那个兜底的res.end(...)依然会被执行,相当于对已经关闭的流再次写入结束操作,直接触发报错。 - 请求
/about路径时会完全重复相同的错误逻辑。
修复方案
有两种和你原有代码风格适配性最高的改法,选任意一种即可:
- 把独立的if判断改成互斥的分支结构,让命中匹配路径后直接进入对应分支,不再走到兜底逻辑
const http = require('http') const server = http.createServer((req, res)=>{ if(req.url === '/') { res.end('Welcome to our home page') } else if(req.url === '/about') { res.end('Here is our short history') } else { res.end(` <h1>Ooops</h1> <p>This is not the page you are looking for</p> <a href="/">backHome</a> `) } }) server.listen(5000) - 保留原有独立if的写法,在每个分支调用完
res.end()后加上return,中断当前请求处理函数的后续执行const http = require('http') const server = http.createServer((req, res)=>{ if(req.url === '/') { res.end('Welcome to our home page') return } if(req.url === '/about') { res.end('Here is our short history') return } res.end(` <h1>Ooops</h1> <p>This is not the page you are looking for</p> <a href="/">backHome</a> `) }) server.listen(5000)
通用排查思路
后续遇到同类write after end报错时,可以顺着两个方向快速定位:
- 同步逻辑层面检查是否存在分支判断没有互斥、没有中断,导致对同一个res对象重复调用end/write方法
- 异步逻辑层面检查是否存在响应已经end后,异步回调(比如定时器、接口请求回调)才执行,在已关闭的响应流上做写入操作
内容的提问来源于stack exchange,提问作者oORiggsOo
相关产品推荐
相关产品推荐

