express.js使用回调时的请求/响应对象生命周期

par*_*r8r 4 javascript lifecycle garbage-collection callback express

如果这是一个多余的问题,请随时解答我.(在我询问之前,我已尽可能多地搜索)

我拼命想要了解请求/响应对象的生命周期.

请考虑以下框架代码:

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.
}
Run Code Online (Sandbox Code Playgroud)

(请注意,原始代码更多,例如检查'Cookie'是否存在等等)

我理解创建了req和res对象,并且必须在某些时候收集垃圾.(人们希望)

当使用setCookie作为参数调用findCookieInDatabase()时,我假设setCookie当时只是一个字符串(包含函数),并且在findCookieInDatabase()中遇到callback(setCookie)语句之前不会被解析或执行.

我也明白,我可能完全错误的上述假设,这可能是由于我对javascript回调的胆量缺乏了解.(我在这方面也进行了很多搜索,但我发现的是如何使用回调的无穷无尽的东西.没有什么在引擎盖下)

所以问题是:javascript(或node.js)如何知道保持'res'活着多久以及什么时候可以垃圾收集呢?

setCookie中的行res.sendfile是否实际上充当了活动引用,因为它是通过findCookieInDatabase()调用的?

javascript是否实际上跟踪所有引用并保持req和/或res,只要任何被调用/回调/事件的任何部分都存活?

任何帮助非常感谢.谢谢阅读.

Eth*_*own 14

你的代码和你的假设有很多,这表明你应该学习一些JavaScript基础知识.我会推荐以下书籍:

当然还有我自己的书,带有Node和Express的Web开发.好的,既然我已经把所有的阅读材料都拿走了,那么让我试着深入了解你的问题.

当节点接收到HTTP请求时,它创建reqres对象(开始他们生活的实例http.IncomingMessagehttp.ServerResponse分别地).这些对象的预期目的是只要HTTP请求就生效.即,客户端发出一个HTTP请求,reqres被创建的对象,一堆东西发生,最后的一个方法res发送的HTTP响应返回给客户端被调用,并且在该点的对象不再需要.

由于节点的异步性,可能有多个req,并res在任何特定时间的对象,只有在他们居住的范围来区分.这可能听起来令人困惑,但在实践中,您永远不必担心:当您编写代码时,您将其编写为就像您始终处理一个HTTP请求一样,并且您的框架(例如,Express)管理多个要求.

JavaScript确实有一个垃圾收集器,它最终在引用计数降为零后释放对象.因此,对于任何给定的请求,只要有req对象的引用(例如),该对象就不会被释放.这是一个Express程序的简单示例,它始终保存每个请求(顺便说一下,这是一个糟糕的主意):

var allRequests = [];
app.use(function(req, res, next) {
    allRequests.push(req);
    next();
});
Run Code Online (Sandbox Code Playgroud)

这是一个可怕的想法的原因是,如果你永远不会删除对象allRequests,你的服务器最终会在处理流量时耗尽内存.

通常,使用Express,您将依赖于异步函数,这些函数在完成工作后调用回调.如果回调函数具有对reqres对象的引用,则在异步函数完成并且回调执行(并且所有其他引用自然超出范围)之前,它们将不会被释放.这是一个只生成人为延迟的简单示例:

app.get('/fast', function(req, res) {
    res.send('fast!');
});

app.get('/slow', function(req, res) {
    setTimeout(function() {
        res.send('sloooooow');
    }, 3000);
});
Run Code Online (Sandbox Code Playgroud)

如果您导航到/slow,您的浏览器将旋转3秒钟.在另一个浏览器中,如果您访问/fast了很多次,您会发现它仍然有效.这是因为Express正在为每个请求创建一个req和一个res对象,其中没有一个会相互干扰.但是res/slow请求关联的对象未被释放,因为回调(持有对该实例的引用)尚未执行.

在一天结束的时候,我觉得你是在过度思考.当然,了解基础知识是件好事,但在大多数情况下,JavaScript中的引用计数和垃圾收集并不是您必须考虑或管理的事情.

我希望这有帮助.