如何在 node.js+express 中捕获“响应结束”事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11137648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I capture a "response end" event in node.js+express?
提问by Jake
I'd like to write an express middleware function that sets up a listener on the response's 'end' event, if one exists. The purpose is to do cleanup based on the http response code that the end handler decided to send, e.g. logging the response code and rollback/commit of a db transaction. i.e., I want this cleanup to be transparent to the end caller.
我想编写一个快速中间件函数,它在响应的“结束”事件上设置一个侦听器(如果存在)。目的是根据最终处理程序决定发送的 http 响应代码进行清理,例如记录响应代码和数据库事务的回滚/提交。即,我希望这个清理对最终调用者是透明的。
I'd like to do something like the following in express:
我想在 express 中执行以下操作:
The route middleware
路由中间件
function (req, res, next) {
res.on ('end', function () {
// log the response code and handle db
if (res.statusCode < 400) { db.commit() } else { db.rollback() }
});
next();
}
The route:
路线:
app.post ("/something", function (req, res) {
db.doSomething (function () {
if (some problem) {
res.send (500);
} else {
res.send (200);
}
});
}
When I try this, the 'end' event handler never gets called. The same for res.on('close'), which I read about in another post. Do such events get fired?
当我尝试这个时,'end' 事件处理程序永远不会被调用。同样的res.on('close'),我在另一篇文章中读到过。这样的事件会被解雇吗?
The only other way I can think of doing this is wrapping res.endor res.sendwith my own version in a custom middleware. This is not ideal, because res.endand res.senddon't take callbacks, so I can't just wrap them, call the original and then do my thing based on the response code that got set when they call me back (because they won't call me back).
我能想到的唯一另一种方法是在自定义中间件中包装res.end或res.send使用我自己的版本。这并不理想,因为res.end并且res.send不接受回调,所以我不能只是包装它们,调用原始然后根据他们给我回电时设置的响应代码做我的事情(因为他们不会打电话我回来了)。
Is there a simple way to do this?
有没有一种简单的方法可以做到这一点?
采纳答案by Florian Margaine
Reading the documentation, here is the signature of res.send:
阅读文档,这里是签名res.send:
res.send(body|status[, headers|status[, status]])
Which means you can set your own status, like this: res.send( 'some string', 200 );or even just res.send( 404 );.
这意味着您可以设置自己的状态,如下所示:res.send( 'some string', 200 );或者甚至只是res.send( 404 );.
This method is the one you use to sendthe response.
此方法是您用来发送响应的方法。
Once it is sent to the client, you can't access it anymore, so there is no callback.
一旦它被发送到客户端,你就不能再访问它,所以没有回调。
This is the last thing your server does. Once it has processed the request, it sends the response.
这是您的服务器所做的最后一件事。一旦它处理了请求,它就会发送响应。
However, you can access it beforeyou send it to the client. Which means you can:
但是,您可以在将其发送给客户端之前访问它。这意味着您可以:
console.log( res );
res.send( datas );
If you want to rollback/commit, you do it when the database's callback is called, not when the response is gone.
如果要回滚/提交,请在调用数据库的回调时执行,而不是在响应消失时执行。
回答by Aveius
Strangely enough, it appears that the response emits a "finish" event when the response is closed: http://sambro.is-super-awesome.com/2011/06/27/listening-for-end-of-response-with-nodeexpress-js/
奇怪的是,当响应关闭时,响应似乎会发出“完成”事件:http: //sambro.is-super-awesome.com/2011/06/27/listening-for-end-of-response- with-nodeexpress-js/
Despite this blog entry being a bit old, this event still exists (Line 836 in lib/http.js), so I assume it won't disappear soon, even though neither node's nor express' documentation mention it. By early 2014 it has moved to line 504 on of lib/_http_outgoing.jsand still works.
尽管这个博客条目有点旧,但这个事件仍然存在(lib/http.js 中的第 836 行),所以我认为它不会很快消失,即使 node 和 express 的文档都没有提到它。到 2014 年初,它已移至lib/_http_outgoing.js 的第 504 行,并且仍然有效。
By the way, the "error" event on a server response is probably not something you'd usually want to see.
顺便说一句,服务器响应上的“错误”事件可能不是您通常想要看到的。
回答by dmon
Just to further @Amatsuyu's response, here's how it should look:
只是为了进一步@Amatsuyu的回应,它应该是这样的:
res.on('finish', function() {
// do stuff here
});

