node.js - 在 Express js 中,如何正确结束抛出错误的流响应

标签 node.js express stream

badStream.pipe(res)

badStream 抛出错误时,响应不会终止,浏览器中的请求会陷入待处理状态。

badStream.on(error, function() {this.end()}).pipe(res)

我已经尝试了以上方法,但没有效果。在这种情况下处理错误的正确方法是什么?感谢您的帮助。

最佳答案

在nodejs中,通过管道传输到http响应流的readstream上的错误只会将其从响应流中取消传输,但不会对其通过管道传输到的响应流执行任何操作。这使得它作为一个打开的套接字挂起,浏览器仍在等待它完成(正如您所观察到的)。因此,您必须手动处理错误并对目标流执行某些操作。

badStream.pipe(res);
badStream.on('error', err => {
  // log the error and prematurely end the response stream
  console.log(err);
  res.end();
});

因为这是一个http响应,并且您已经在发送http响应正文,因此http状态和 header 已经发送,所以在发送过程中您可以做的事情并不多响应正文。

最终,您必须调用 res.end() 来终止响应,以便浏览器知道请求已完成。如果此响应上有一个内容长度 header (提前知道长度),那么在完成之前终止响应流将导致浏览器看到它没有获得整个响应,从而知道发生了某些事情错了。

如果响应中没有内容长度,那么它实际上取决于您发送的数据类型。如果您只是发送文本,那么浏览器可能不会知道存在错误,因为文本响应将结束。如果它是人类可读的文本,您可以发送“错误,错误,错误 - 响应提前结束”或一些可见的文本标记,这样人们可能会意识到响应不完整。

如果它是某种特定格式的数据,例如 JSON 或 XML 或任何多部分响应,那么过早挂起套接字可能会导致客户端注意到的解析错误。不幸的是,http 并没有真正针对中间响应错误做出规定,因此将其留给各个应用程序来检测和处理。

仅供引用,这是一个漂亮的 interesting article其中涵盖了很多有关流的错误处理的内容。并且,请注意使用 stream.pipeline()代替 .pipe() 还可以进行更完整的错误处理,包括为您提供一个回调,该回调将在任一流中出现错误时调用,并且会自动调用 .destroy() 在所有流上。在很多方面,stream.pipeline(src, dest) 旨在取代 src.pipe(dest)

关于node.js - 在 Express js 中,如何正确结束抛出错误的流响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68331843/

相关文章:

javascript - 如何将 createProxyMiddleware 与嵌套逻辑一起使用

javascript - Express js 路由器不工作

javascript - Electron 构建应用程序无法启动 Express 服务器

c# - 复制流的最后 16 个字节以外的所有字节?流结束的早期检测?

node.js - 使用 Node.js 进行网页抓取时,是否可以在页面上运行所有 JavaScript? (即模拟一个真实的浏览器?)

node.js - Typescript 生成的 javascript 不起作用

firebase - Flutter Firestore StreamBuilder 最初获得空值

python - 解析Python中分块的内容类型的响应

javascript - 在 NodeJS 中使用变换/双工流

javascript - UnhandledPromiseRejectionWarning : Error: URI does not have hostname, 域名和顶级域名