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

Pet*_*tai 12 javascript architecture connect node.js

我想实现这样的目标:

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);
Run Code Online (Sandbox Code Playgroud)

当我为地址卷曲时,我得到一个控制台的例外,抱怨在发送之后标题不会被打扰,这是公平的.只是我不接触响应对象.

/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)
Run Code Online (Sandbox Code Playgroud)

调试NodeJS/Connect层我进入了一个部分,它以某种方式暗示如果已经发送了头,那么执行路由处理程序必须初始化响应头.

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

Wei*_*iao 27

不确定您是否找到了解决方案.

如果要为请求周期设计后处理器,可以使用侦听响应对象上的"finish"事件的中间件.像这样:

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();
});
Run Code Online (Sandbox Code Playgroud)

附加到"完成"事件的功能将在写出响应后执行(这意味着NodeJS已将响应头和主体切换到OS以进行网络传输).

我想这一定是你想要的.

  • 如果响应对象已经触发了`close`事件,则不会触发`finish`事件 - 它会在套接字关闭之前发生,然后才能发送响应.如果你想捕获请求/响应周期结束的时刻(即使错误处理中间件发送响应),也许最好覆盖响应的`end`函数:`var _end = res.end; res.end = function(){console.log('响应的最后一部分'); _end.apply(this,arguments); }` (2认同)