如果这是一个多余的问题,请随时解答我。 (在问之前我已经尽可能多地搜索了)
我拼命想要了解请求/响应对象的生命周期。
考虑以下框架代码:
app.get('/', function(req, res) {
var setCookie = function(err, idCookie) { //callback after cookieSearch in DB
// ... do something with the result of findCookieInDatabase() (handle error, etc.);
res.sendfile('index.html');
}
var cookie = parseCookie(req.get('Cookie')); //parse and format cookie
findCookieInDatabase(cookie, afterCookieSearch); //tries to find cookie is DB
// .. do some content return stuff, etc.
}
(请注意,原始代码会更多,例如检查Cookie是否存在等等。)
我理解创建了req和res对象,并且必须在某些时候收集垃圾。 (人们希望)
当使用setCookie作为参数调用findCookieInDatabase()时,我假设setCookie当时只是一个字符串(包含函数),并且在遇到回调(setCookie)语句之前不会被解析或执行在findCookieInDatabase()中。
我也理解我可能完全错误的上述假设,这可能是由于我对javascript回调的缺乏了解。 (我已经在这方面进行了很多搜索,但是我能找到的却是关于如何使用回调的无穷无尽的东西。没有什么关于引擎盖下的内容)
所以问题是: javascript(或node.js)如何知道保持多久' res'还活着什么时候垃圾收集它可以吗?
setCookie中的res.sendfile行实际上是否作为活动引用,因为它是通过findCookieInDatabase()调用的?
javascript是否实际上跟踪所有引用并保持req和/或res,只要任何被调用/回调/事物的任何部分都存活?
任何帮助非常感谢。谢谢你的阅读。
答案 0 :(得分:13)
你的代码还有很多 - 以及你的假设 - 这表明你应该学习一些JavaScript基础知识。我会推荐以下书籍:
当然是我自己的书,Web Development with Node and Express。好的,既然我已经把所有阅读材料都拿走了,那么让我试着深入探讨你的问题。
当Node收到HTTP请求时,它会创建req
和res
个对象(分别以http.IncomingMessage
和http.ServerResponse
的实例开始生效。这些对象的预期用途就是它们只要HTTP请求就存在。也就是说,客户端发出HTTP请求,创建req
和res
个对象,发生一堆事情,最后调用res
上的方法,发送HTTP响应到客户端,此时不再需要这些对象。
由于Node的异步性质,在任何给定时间可能有多个req
和res
个对象,仅区别于它们所处的范围。这可能听起来令人困惑,但在实践中,您永远不必担心:当您编写代码时,您将其编写为就像您始终处理一个HTTP请求一样,并且您的框架(例如,Express)管理多个请求。
JavaScript确实有一个垃圾收集器,它最终会在引用计数降为零后释放对象。因此,对于任何给定的请求,只要有req
对象的引用(例如),该对象就不会被释放。这是一个Express程序的简单示例,它始终保存每个请求(顺便说一下,这是一个糟糕的主意):
var allRequests = [];
app.use(function(req, res, next) {
allRequests.push(req);
next();
});
这是一个可怕的想法的原因是,如果你永远不会从allRequests
中删除对象,那么你的服务器在处理流量时最终会耗尽内存。
通常,使用Express,您将依赖异步函数,这些函数在完成工作后调用回调。如果回调函数具有对req
或res
对象的引用,则在异步函数完成并且回调执行(并且所有其他引用自然超出范围)之前,它们将不会被释放。这是一个简单的例子,它只会产生一个人工延迟:
app.get('/fast', function(req, res) {
res.send('fast!');
});
app.get('/slow', function(req, res) {
setTimeout(function() {
res.send('sloooooow');
}, 3000);
});
如果您导航到/slow
,您的浏览器将旋转3秒钟。在另一个浏览器中,如果您多次访问/fast
,您会发现它仍然有效。这是因为Express正在为每个请求创建一个req
和res
对象,其中没有一个会相互干扰。但是,与res
请求关联的/slow
对象未被释放,因为回调(持有对该实例的引用)尚未执行。
在一天结束的时候,我觉得你想要过度思考。当然,理解基础知识是件好事,但在大多数情况下,JavaScript中的引用计数和垃圾收集不是你必须考虑或管理的事情。
我希望这会有所帮助。