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/