有人可以解释一个函数包装来自howtonode的成语吗?

时间:2013-03-08 22:30:12

标签: javascript node.js closures connect

我最近开始使用node.js,express& MongoDB的。由于express使用connect来提供中间件支持,我开始阅读中间件并连接。

我在howtonode.org上看到了以下示例:

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

的调用

这是什么意思?

2 个答案:

答案 0 :(得分:3)

它正在拦截对res.writeHead的调用,添加一些日志记录,然后将调用委托给原始res.writeHead

对于方法拦截来说,这就像是一个超级简单的AOP。

答案 1 :(得分:1)

让我们分解这里发生的事情

wrapping idiom to hook into the call to writeHead

在标准 express 流程中,收到请求( req )并准备响应( res )。 ( req res )对可以通过一系列过滤器进行级联,这些过滤器可以修改 req 并准备 res

在流程中的某一点, res 将被视为充分准备好响应的标头可以发送到客户端。将为此目的调用 res.writeHead *函数。

这个函数的原型是函数(代码,头文件),为了记录要发送的头文件,你需要在这个时刻挂钩代码并做一个< / p>

console.log("Response " + code + " " + JSON.stringify(headers));

在某种程度上,如果代码中的orgininal函数是

res.writeHead = function(code, headers) {
    // original code
}

您想用

替换此代码
res.writeHead = function(code, headers) {
    console.log("Response " + code + " " + JSON.stringify(headers));
    // original code
}

在某种程度上,您希望在writeHead函数的开头“插入”一段代码。

但是你不应该尝试修改原始的writeHead代码,因为你甚至可能不知道这段代码的编写地点,也不想开始查找。所以你想要劫持这个函数:当一段代码调用res.writeHead时,你需要调用你的函数。

这样做的方法就是

return function logItHandle(req, res, next) {
   res.writeHead = function (code, headers) {
       console.log("Response " + code + " " + JSON.stringify(headers));
   }
   next(); 
}

但如果你只是这样做,你会遇到一些麻烦,因为原来的writeHead代码丢失了,不会被调用。因此,标题将被记录,但不会发送给客户端!

你需要一种方法来“记住”原始代码并在writeHead变体的末尾调用它:

return function logItHandle(req, res, next) {

   // save the original writeHead function so that it can be referenced in the closure
   var originalWriteHead = res.writeHead; 

   res.writeHead = function (code, headers) {

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

       // make as if our hook never existed in the flow
       res.writeHead = originalWriteHead ;

       // call the original writeHead because otherwise the external code
       // called our implementation of writeHead instead of the original code
       res.writeHead(code, headers);

   }
   next(); 
}