Javascript NodeJS连接中间件功能设置

Javascript NodeJS连接中间件功能设置,javascript,node.js,Javascript,Node.js,我试图了解中间件是如何工作的,特别是NodeJS的Connect模块。我仔细研究了一下,发现了这个例子: module.exports = function logItSetup() { // Initialize the counter var counter = 0; return function logItHandle(req, res, next) { var writeHead = res.writeHead; // Store the original fu

我试图了解中间件是如何工作的,特别是NodeJS的Connect模块。我仔细研究了一下,发现了这个例子:

module.exports = function logItSetup() {

  // Initialize the counter
  var counter = 0;

  return function logItHandle(req, res, next) {
    var writeHead = res.writeHead; // Store the original function

    counter++;

    // Log the incoming request
    console.log("Request " + counter + " " + req.method + " " + req.url);

    // Wrap writeHead to hook into the exit path through the layers.
    res.writeHead = function (code, headers) {
      res.writeHead = writeHead; // Put the original back

      // Log the outgoing response
      console.log("Response " + counter + " " + code + " " + JSON.stringify(headers));

      res.writeHead(code, headers); // Call the original
    };

    // Pass through to the next layer
    next();
  };
};
所以我知道它会记录传入的请求和响应。但是,即使文章给出了以下解释,我仍然不理解您需要用替换函数替换写头:

“设置函数是设置中间件跨请求使用的变量的好地方。在本例中,我们正在初始化记录器的计数器

在处理程序中,我们使用一个包装习惯用法来钩住对writeHead的调用。在JavaScript中,函数与其他任何函数一样都是值。因此包装函数的一个好方法是将对原始实现的引用存储在闭包变量中。将函数替换为新函数,并在新函数的第一行中,放置旧函数nction定义返回。然后在替换函数的最后一行调用原始函数。这是一种简单而有效的方法来连接现有的对象方法,因为它们只按名称查找属性,而不引用实际的函数对象


独立的console.log调用将在每个请求周期开始时调用,嵌套的console.log将在退出时通过嵌套的writeHead函数调用。”

每次有传入请求时,它都会通过堆栈中间件。这些简单的函数采用3个参数
req
res
next
,有点像这样:

function someMiddleware(req,res,next){
  // do stuff with request & response...

  // You need to call next to keep going through the stack
  next(); 
}
connect()
.use(function(req,res,next){
  //some other handler
  // ...
  // Call next
  next();
})
.use(logInSetup) //Assuming you named it like this
在您的示例中,您可以使用如下模块:

function someMiddleware(req,res,next){
  // do stuff with request & response...

  // You need to call next to keep going through the stack
  next(); 
}
connect()
.use(function(req,res,next){
  //some other handler
  // ...
  // Call next
  next();
})
.use(logInSetup) //Assuming you named it like this
模块
返回的
函数正是堆栈中间件所期望的函数。这是。。。这基本上是相同的想法

writeHead
函数存储在一个变量中,因此您可以对每个请求调用
console.log
,然后调用实际函数。考虑到调用此函数时不会调用
writeHead
,而是从其他地方调用
res.writeHead
时。 这是一种(非常聪明的)修改函数而不改变其原始实现的方法

一个非常简单的例子:

//Assume this function is a dependency and cannot be alter
function sumNums(a,b){
  return a + b;
}

var sumNums_copy = sumNums;

function sumNums(a,b) {
  console.log('Log and the sum');
  sumNums_copy(a,b);
};

sumNums_copy(2,2); // sums
sumNums(2,2); // sums and logs
函数是javascript中的第一类对象,这意味着它们可以作为参数传递给其他函数、从函数返回或存储在变量中