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()