Javascript 调用responde.end()后,如何让NodeJS/connect中间件执行?
我想实现这样的目标:Javascript 调用responde.end()后,如何让NodeJS/connect中间件执行?,javascript,node.js,architecture,connect,Javascript,Node.js,Architecture,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
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)
调试NodeJS/Connect层时,我遇到了这样一个问题:如果已经发送了头,那么执行路由处理程序必须初始化响应头
问题是上述行为是否是故意的(即在路由处理程序完成发送响应后执行任何代码是完全不可想象的,或者这只是连接中的一个错误?我认为这是一个糟糕的规划问题。你应该以更好的方式解决这个问题。我不知道为什么要将请求处理程序和请求后处理器分开,但让我们看看是什么我们能做到 因此,是的,在响应结束后,您不能再次阅读标题 因此,在调用后处理器之前,不要完成响应
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();
});
这是一种解决方案,但这可能不是解决问题的最佳方法
在我看来,在响应完成后调用next()
真的很糟糕。如果需要后处理器,为什么要在请求过滤器中这样做(或者这是什么)。调用函数,而不是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是否为true,如果为true,则抛出错误
如果将第14行修改为:
app.use("/api", function(req, res, next){
console.log("request handler");
res.end("hello");
console.log(res);
next();
});
您将看到它实际上将“headersSent”设置为true。因此,在我们结束请求后,您可以从next()代码中看到,由于讨论的条件,它抛出了错误。不确定是否找到了解决方案 如果要为请求周期设计后处理器,可以使用侦听响应对象上的“完成”事件的中间件。如下所示:
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”事件的函数将在写入响应后执行(这意味着NodeJS已将响应头和响应体交给操作系统进行网络传输)
我想这一定是你想要的。你正在做
res.end(“你好”)
在您的代码中是的。响应处理完成,响应准备好传输。现在,我想放置一个日志或清理一些东西。自从您提出这个问题以来,您找到了这样做的方法吗?这个线程上似乎没有响应,我试图理解为什么Connect团队以是的。没有,我还没有找到任何解决方案,所以从需要的特性中选择。是的,但是发送请求并不一定意味着我们已经完成了请求周期。IHHO只是一种可能的方法。考虑到NoDEJS/Connect层填充了来自各种来源的混合逻辑:A)表示业务逻辑的代码和表示基础结构的代码。因此,如果两个不同的ppl创建了业务和基础设施部分,那么这里就不能进行协作/强耦合的功能开发。业务逻辑人员必须处理一些事情,比如他独自运行(不知道基础结构),基础结构代码也需要这样做:对业务层代码不可知。再说一次:在最后一个函数(“后处理器”)中,我没有触及头,实体任何已冻结的对象。finish
事件不会在响应对象已触发close
事件的情况下触发-当套接字在可以发送响应之前关闭时发生。如果您想要捕捉请求/响应周期结束的时刻(即使错误处理中间件发送响应时),那么最好覆盖响应的end
函数:var\u end=res.end;res.end=function()