我试图了解中间件的工作原理,特别是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。“
答案 0 :(得分:1)
每次有传入请求时,它都会通过堆栈中间件。这些是简单的函数,需要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
模块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中的第一类对象,意味着它们可以作为参数传递给其他函数,从函数返回或存储在变量中。