Why can I execute code after "res.send"?
我想知道以下代码行为背后的机制是什么:
1 2
| res.send(200, { data: 'test data' });
console.log('still here...'); |
我的理解是 res.send 不会返回函数,但会关闭连接/结束请求。这可以解释为什么我仍然可以在 res.send 命令之后执行代码(我查看了 express 源代码,它似乎不是异步函数)。
还有什么我可能会遗漏的东西吗?
- 抱歉,我误读了您的帖子,并且不确定您的代码有什么问题,因为它完全合法。当您调用 send 时,它只是将数据从 http 连接中输出,您的代码将继续。如果你想终止代码,你可以使用 return ,或者不写任何东西。很抱歉误解。
当然 end 会结束 HTTP 响应,但它不会对您的代码做任何特别的事情。
即使您结束了回复,您也可以继续做其他事情。
然而,你不能用 res 做任何有用的事情。由于响应已结束,您无法向其写入更多数据。
1 2
| res.send(...);
res.write('more stuff'); // throws an error since res is now closed |
这种行为与其他传统框架(PHP、ASP 等)不同,后者为 HTTP 请求分配线程并在响应结束时终止线程。如果您调用类似 ASP 的 Response.End 之类的等效函数,线程将终止并且您的代码将停止运行。在节点中,没有线程可以停止。 req 和 res 不会再触发任何事件,但回调中的代码可以继续运行(只要它不尝试调用 res 上需要打开有效响应的方法) .
- 啊好的,所以请求发送后我们可以继续代码的原因是因为节点中没有线程可以停止?所以浏览器,响应被发送,连接被关闭,但这并不意味着脚本已经退出。我以前利用过这种行为,但不确定它背后的原因。
-
关于发送后如何返回函数的任何想法?
-
我的意思是停止执行,破坏功能。
-
@OscarVGG:不,没有什么可以停止的(除了退出过程)。
-
换句话说,node.js 不像 php 应用程序上下文 = 请求上下文。
-
我正在寻找的答案是 return callback();。我认为这被称为"短路"。对不起,如果我不能以正确的方式问它
-
@OscarVGG:这并不是真正的短路,它具有明确的含义。那只是调用回调并返回。
-
这个答案非常有帮助,并说服我出于意识形态原因离开 nodejs。
-
@jkatzer 意识形态很弱。实用主义获胜。
-
@我同意这一点,但是我怎样才能在 res.end 之后停止执行代码
-
@PrabjotSingh 总是写 return res.send(...); 或 return res.end();
-
这并不能真正保证任何事情——范围内的异步回调仍然可以运行。
-
当然,尽量记住 Node 只是一个执行环境,如果你使用 expressjs,这是你的 web 服务器。您所说的就像想知道为什么 Apache 在 php 返回响应后继续运行。您可以选择使用这个额外的容量,也许您想在响应发送后记录响应的状态,或者执行一些其他应用程序功能,这取决于您。然而,权力越大,责任越大……
-
@AnatolyG 在阅读此评论部分时,我至少阅读了您的评论 5 次,并且我每次都阅读抄袭并对此大笑,现在是在我自己身上。哈哈。
编辑:我不再做下面解释的事情,因为你不应该在不需要它的时候返回一个值。它使您的代码可读性降低并且看起来很hackish。相反,我建议将 return 语句与 res.send() 分开。 @slavafomin 在评论中很好地解释了这一点。
停止执行函数并同时发送响应的一种简单方法是执行
1
| return res.send('500', 'Error message here'); |
这允许您使用简短的 if 语句来处理错误,例如:
1 2 3
| if (err) {
return res.send('500', 'Error message here');
} |
res.send 函数的确切返回是一个对象,它似乎包含您结束连接后的整个连接状态(请求、状态、标头等),但这应该不重要,因为您不会用它做任何事情。
-
这是一个很好的观点,但在技术上不是答案。因为问题更多是关于为什么而不是如何。尽管如此,还是有很大的贡献,因此赞成:)。
-
是的,当时我无法发表评论,所以我不得不发布答案。
-
我建议不要使用这种技术。它使代码更短,但也使它变得不那么有意义和模糊,因为它使用了不正确的语义。如果你没有使用函数中的值,那么你不应该返回一个。它还可以破坏类型化的 JavaScript(如 TypeScript)和使用静态代码分析的工具。换句话说:它看起来很老套而且不专业。
-
@SlavaFominII 可以是这样的: res.send('500', 'Error message here');return; 在 if 语句中。
-
@SlavaFominll 我认为这种方法很常见,你不能再称之为hackish了。至于静态分析器 - 由于快速开发人员是处理此函数返回的人,我很确定没有太多可担心的。你遇到过具体问题吗?
-
如果您担心返回未使用的值,可以使用 void 关键字:return void res.send('500', 'Error message here');。这将确保从函数返回 undefined。
一个可能的解决方案是使用这个库:on-finished
1 2 3 4 5 6 7 8 9 10 11 12
| var destroy = require('destroy')
var fs = require('fs')
var http = require('http')
var onFinished = require('on-finished')
http.createServer(function onRequest (req, res) {
var stream = fs.createReadStream('package.json')
stream.pipe(res)
onFinished(res, () => {
destroy(stream)
})
}) |
也适用于 Express,例如:
1 2 3 4 5 6 7 8 9 10
| const express = require('express');
const app = express();
app.get('/video', (req, res) => {
const ffmpeg = spawn(ffmpegPath, argsArray);
ffmpeg.stdout.pipe(res);
onFinished(res, () => {
ffmpeg.kill();
});
}); |