我正在尝试使用带有闭包的curried fn作为服务器request event的回调。
它在客户端第一次发出请求(html被发送和显示)时工作,但第二次页面为空。在调用cb一次后,节点是否擦除了闭包?
// server.js
var pype = function(self, arr, errorHandler, cb) {
var i = 0,
req,
res,
run = function() {
arr[i].call(self, req, res, next);
},
next = function(err) {
if (err && errorHandler) {
return errorHandler.call(self, err, req, res);
}
i++
if (i < arr.length) {
return run();
} else if (cb) {
return cb.call(self, req, res);
}
}
return function(request, response) {
req = request;
res = response;
run();
}
};
var http = require("http”);
var server = http.createServer();
var errorhandler = function(err, req, res) {
res.end(err);
},
var finalHandler = function(req, res) {
res.setHeader("Content-Type", "text/html");
res.end(req.html);
};
var requestHandler = pype(null, [pens, gits, concat, index, sort, html, finalHandler], errorhandler);
// this works only once
server.on('request', requestHandler);
// this works for multiple calls
server.on('request', function(req, res){
var requestHandler = pype(null, [pens, gits, concat, index, sort, html, finalHandler], errorhandler);
requestHandler(req, res);
});
谢谢!
答案 0 :(得分:2)
节点不会删除任何关闭。
我希望你在完成请求或发起新请求时永远不会将i
重置回0
。因为闭包无限期地保留其所有状态,所以当第二个请求进入时,i
将指向数组的末尾,并且您将永远不会调用数组中的任何函数。
您可以在处理请求时或在新请求开始时将i
重置为0
。
从此改变:
return function(request, response) {
req = request;
res = response;
run();
}
到此:
return function(request, response) {
req = request;
res = response;
i = 0;
run();
}
修复该特定问题,但您也有其他问题(见下文)。
看来这个结构还有其他问题。因为你只创建了一个闭包,然后为所有请求重用它,每当你的第一个请求异步处理某个东西而第二个请求到达那个时间时,你将清除第一个请求的闭包变量,这两个将碰撞。对于任何曾经打算一次处理多个请求的服务器而言,这种单永久闭包方案是一种站不住脚的设计。
你的第二次尝试运行得很好是一种更好的方法,因为你为每个请求创建一个新的独立闭包,当多个请求同时处于飞行状态时不会出现竞争条件问题。
我必须说,我真的不认为这里需要咖喱风格。您不希望创建一个持久的闭包,它会无限期地持续存在(每个请求都需要一个新的闭包)。并且,它使您的代码更难理解和遵循。
如果没有讨论,对我来说似乎更简单:
var http = require("http");
var server = http.createServer();
function handleRequest(ctx, req, res, handlers) {
return new Promise(function(resolve, reject) {
var i = 0;
function next(err) {
if (err) {
reject({err, req, res, ctx});
} else {
run();
}
}
function run() {
if (i < handlers.length) {
handlers[i++].call(ctx, req, res, next);
} else {
resolve({req, res, ctx});
}
}
run();
}
}
function errorhandler(info) {
info.res.end(info.err);
}
function finalHandler(info) {
info.res.setHeader("Content-Type", "text/html");
info.res.end(req.html);
}
server.on('request', function(req, res) {
handleRequest(null, req, res, [pens, gits, concat, index, sort, html]).then(finalHandler, errorHandler);
});