如何在调用responde.end()之后执行NodeJS / connect中间件?

我想实现这样的事情:

var c = require('connect'); var app = c(); app.use("/api", function(req, res, next){ console.log("request filter 1"); next(); }); app.use("/api", function(req, res, next){ console.log("request filter 2"); next(); }); app.use("/api", function(req, res, next){ console.log("request handler"); res.end("hello"); next(); }); app.use("/api", function(req, res, next){ console.log("response post processor"); next(); }); app.listen(3000); 

当我蜷缩的地址,我得到一个例外的控制台抱怨标题发送后不会被打扰,这是公平的。 只有我不接触响应对象。

 /usr/bin/node app2.js request filter 1 request filter 2 request handler Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (http.js:644:11) at ServerResponse.res.setHeader (/home/zpace/node_modules/connect/lib/patch.js:59:22) at next (/home/zpace/node_modules/connect/lib/proto.js:153:13) at Object.handle (/home/zpace/WebstormProjects/untitled1/app2.js:25:5) at next (/home/zpace/node_modules/connect/lib/proto.js:190:15) at Object.handle (/home/zpace/WebstormProjects/untitled1/app2.js:19:5) at next (/home/zpace/node_modules/connect/lib/proto.js:190:15) at Object.handle (/home/zpace/WebstormProjects/untitled1/app2.js:14:5) at next (/home/zpace/node_modules/connect/lib/proto.js:190:15) at Function.app.handle (/home/zpace/node_modules/connect/lib/proto.js:198:3) 

debuggingNodeJS / Connect层我进入了一个部分,不知何故意味着如果头已经发送,然后执行一个路由处理程序必须初始化响应头。

问题是,如果上述行为是故意的(即在路由处理程序完成发送响应之后执行任何代码是完全不可想象的,或者这只是连接中的一个错误?

不知道你是否find你的解决scheme。

如果要为请求周期devise后处理器,则可以使用侦听响应对象上的“完成”事件的中间件。 喜欢这个:

 app.use(function(req, res, next){ res.on('finish', function(){ console.log("Finished " + res.headersSent); // for example console.log("Finished " + res.statusCode); // for example // Do whatever you want }); next(); }); 

响应被写出后,执行附加到“finish”事件的function(这意味着NodeJS已经将响应报头和主体交给了用于networking传输的OS)。

我想这一定是你想要的。

我认为这是一个不好的规划问题。 你应该以更好的方式解决这个问题。 我不知道为什么你有一个请求处理程序和请求后处理器分离,但让我们找出我们可以做什么。

所以是的,在响应结束后,你不能再读取标题。

所以在调用后处理器之前不要完成响应。

 var isEnd; app.use("/*", function(req, res, next){ isEnd = false; }) app.use("/api", function(req, res, next){ console.log("request handler"); res.write("hello"); isEnd = true; next(); }); app.use("/api", function(req, res, next){ console.log("response post processor"); if(isEnd) { res.end(); } else next(); }); 

这是一种解决scheme,但这可能不是最适合你的问题。

在我看来,在响应完成之后,你调用next()是非常糟糕的。 如果你需要一个后处理器,为什么你在一个请求filter(或这是什么)中这样做。 调用一个函数,但不是next()

也许这个:

 app.use("/api", function(req, res, next){ console.log("request handler"); res.end("hello"); setTimeout(function(){(postProcessor(req)},0); }); function postProcessor(req) { //doing post process stuff. //response not needed because already ended. } 

或这个:

 app.use("/api", function(req, res, next){ console.log("request handler"); res.writed("hello"); setTimeout(function(){(postProcessor(req)},0); // u cant res.end here because setTimeout. //If you dont use setTimeout you can use res.end here, but not bot function. }); function postProcessor(req, res) { //doing post process stuff. res.end(); } 

next()不是用于这个用法,你使用的是什么。

我希望我的回答可以帮助你,但我知道它并不能涵盖所有的事情,但你的回答并不是真的具体。

尝试用你的早晨咖啡尝试一个很好的问题!

所以通过proto.js ,如果你看下102行,这是app.handle ,它是中间件堆栈的处理程序代码,你会看到next()如何操作。

在函数next()被调用的地方,你可以看到它检查res.headerSent是否为真,如果是的话就会抛出一个错误。

如果将第14行修改为:

 app.use("/api", function(req, res, next){ console.log("request handler"); res.end("hello"); console.log(res); next(); }); 

你会看到它实际上将“headersSent”设置为true。 因此,在我们结束请求之后,您可以从下一个()代码中看到由于讨论的条件而引发错误。