2

我最近开始使用 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 的调用

这意味着什么?

4

2 回答 2

3

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

这就像一个超级简单的 AOP 方法拦截。

于 2013-03-08T22:33:18.430 回答
1

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

wrapping idiom to hook into the call to writeHead

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

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

这个函数的原型是function (code, headers),为了记录将要发送的 headers,你需要在这个时候挂钩代码并做一个

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

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

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(); 
}
于 2013-03-09T09:46:12.910 回答