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

express.js request/response object life cycle when using callbacks

本文关键字:对象 响应 生命 周期 请求 回调 express js      更新时间:2023-09-26

如果这是一个多余的问题,请随时帮我解决。(在询问之前,我已经尽我所能搜索了(

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

考虑以下骨架代码:

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当时只是一个字符串(包含函数(,在findCookieInDatabase((中遇到回调(setCookie(语句之前不会被解析或执行。

我也明白,我可能完全错了上述假设,这可能是由于我对javascript回调的本质缺乏了解。(我也搜索了很多,但我能找到的只是关于如何使用回调的无休止的教程。没有关于引擎盖下的内容(

所以问题是:javascript(或node.js(如何知道"res"的生存时间以及何时可以对其进行垃圾收集?

setCookie中的res.sendfile行是否真的充当了一个活动引用,因为它是通过findCookieInDatabase((调用的?

只要任何被调用/回调的ed/事物的任何部分都是活动的,javascript真的会跟踪所有引用并保持req和/或res的活动吗?

非常感谢您的帮助。感谢阅读。

您的代码和假设发生了很多事情,这向我表明您应该学习一些JavaScript基础知识。我推荐以下几本书:

  • 讲JavaScript,作者:Axel Rauschmayer
  • Douglas Crockford的《JavaScript:好的部分》(请注意:我不认为Douglas Crock ford所说的一切都是黄金,但我认为这本书是有抱负的JavaScript程序员必读的书(
  • 《学习节点》,Shelley Powers著

当然还有我自己的书《使用Node和Express进行Web开发》。好吧,既然我已经把所有的阅读材料都整理好了,让我试着抓住你问题的核心。

当Node接收到HTTP请求时,它会创建reqres对象(它们分别作为http.IncomingMessagehttp.ServerResponse的实例开始使用(。这些对象的预期用途是它们的寿命与HTTP请求的寿命一样长。也就是说,客户端发出HTTP请求,创建reqres对象,发生一堆事情,最后调用res上的一个方法,将HTTP响应发送回客户端,此时不再需要这些对象。

由于Node的异步特性,在任何给定时间都可能有多个reqres对象,仅通过它们所处的范围来区分。这听起来可能令人困惑,但在实践中,您永远不必担心这一点:当您编写代码时,您编写代码的方式就好像您总是在处理一个HTTP请求一样,而您的框架(例如Express(管理多个请求。

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

var allRequests = [];
app.use(function(req, res, next) {
    allRequests.push(req);
    next();
});

这是一个糟糕的想法,因为如果你从不从allRequests中删除对象,你的服务器在处理流量时最终会耗尽内存。

通常,使用Express,您将依赖异步函数,这些函数在完成工作后会调用回调。如果回调函数具有对reqres对象的引用,则在异步函数完成并执行回调之前(当然,所有其他引用都超出了作用域(,不会释放这些对象。这里有一个简单的例子,只会产生人为的延迟:

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为每个请求创建一个reqres对象,它们都不会相互干扰。但是,与/slow请求相关联的res对象没有被解除分配,因为回调(保存对该实例的引用(尚未执行。

一天下来,我觉得你想得太多了。当然,了解基本原理是件好事,但在大多数情况下,JavaScript中的引用计数和垃圾收集不是你必须考虑或管理的事情。

我希望这能有所帮助。