NodeJS Connect中间件功能设置

时间:2013-09-23 21:33:16

标签: javascript node.js

我试图了解中间件的工作原理,特别是NodeJS的Connect模块。我正在浏览这个http://howtonode.org/connect-it并找到了这个例子:

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:

“设置功能是设置中间件跨请求使用的变量的好地方。在这种情况下,我们正在初始化记录器的计数器。

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

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

1 个答案:

答案 0 :(得分:1)

每次有传入请求时,它都会通过堆栈中间件。这些是简单的函数,需要3个参数reqresnext,并且有点像这样:

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

模块returns一个正是堆栈中间件所期望的功能。这是how connects does it ......这基本上是一样的想法。

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中的第一类对象,意味着它们可以作为参数传递给其他函数,从函数返回或存储在变量中。