8

Please feel free to sort me out if this is a redundant question. (I have searched as much as I can bear before asking)

I am desperately trying to understand the life cycle of the request/response objects.

Consider the following skeleton code:

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.
}

(Please note that the original code does a whole lot more, such as checking if 'Cookie' even exists etc.)

I uderstand that req and res objects are created and must be at some point garbage collected. (One would hope)

When findCookieInDatabase() is called with setCookie as a parameter I'm assuming that setCookie is just a string (containing the function) at the time and does not get parsed nor executed until the callback(setCookie) statement is encountered in findCookieInDatabase().

I also understand that I might be utterly wrong with the above assumption which would be due to my lack of understanding the guts of javascript callbacks. (I have searched a lot on this also but all I could find is endless tuts on how to use callbacks. Nothing on what's under the hood)

So the question is this: How does javascript (or node.js) know how long to keep 'res' alive and when is it ok to garbage collect it?

Does the line res.sendfile in setCookie actually act as an active reference because it is invoked through findCookieInDatabase()?

Does javascript actually keep track of all the references and keeps req and/or res alive so long as any part of any called/callback-ed/things are alive?

Any help greatly appreciated. Thanks for reading.

3
  • 1
    I hate to say it, but there's so much going wrong with your code and your assumptions that I'm not even sure how to start answering your questions. I would start with some tutorials on callback functions (you say you're using one, but there's no evidence of that in the code you posted), and understand how function-level scope and closures works in JavaScript. Commented Jun 25, 2014 at 4:40
  • Ethan, Despite you wondering the contrary, you did give me a great keyword to begin with - closures. It did clear up a good chunk of missing information so thank you.What still remains for me to understand/research (which is what the OP is mostly about) is how can I make sure 'req' & 'res' will be garbage collected and I don't do something which causes them to be kept around indefinitely. I'm not finding much about this but I'll keep digging. Commented Jun 25, 2014 at 19:40
  • Glad to hear it. I'll try to add an answer that will help further with your question. Commented Jun 25, 2014 at 20:00

1 Answer 1

24

There's a lot going on with your code -- and your assumptions -- that indicates to me that you should study some JavaScript fundamentals. I would recommend the following books:

And of course my own book, Web Development with Node and Express. Okay, now that I've got all the reading material out of the way, let me try to get to the heart of your question.

When Node receives an HTTP request, it creates the req and res objects (which begin their life as instances of http.IncomingMessage and http.ServerResponse respectively). The intended purpose of those objects is that they live as long as the HTTP request does. That is, the client makes an HTTP request, the req and res objects are created, a bunch of stuff happens, and finally a method on res is invoked that sends an HTTP response back to the client, and at that point the objects are no longer needed.

Because of Node's asynchronous nature, there could be multiple req and res objects at any given time, distinguished only by the scope in which they live. This may sound confusing, but in practice, you never have to worry about that: when you write your code, you write it as if you were always ever dealing with one HTTP request, and your framework (Express, for example), manages multiple requests.

JavaScript does indeed have a garbage collector, which eventually deallocates objects after their reference count drops to zero. So for any given request, as long as there's a reference to the req object (for example), that object will not be deallocated. Here's a simple example of an Express program that always saves every request (this is a terrible idea, by the way):

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

The reason this is a terrible idea is that if you never remove objects from allRequests, your server will eventually run out of memory as it processes traffic.

Typically, with Express, you'll rely on asynchronous functions that invoke a callback once they've done their work. If the callback function has a reference to the req or res objects, they will not be deallocated until the asynchronous function completes and the callback executes (and all other references are out of scope, naturally). Here's a simple example that just generates an artificial delay:

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

app.get('/slow', function(req, res) {
    setTimeout(function() {
        res.send('sloooooow');
    }, 3000);
});

If you navigate to /slow, your browser will spin for 3 seconds. In another browser, if you access /fast a bunch of times, you'll find that it still works. That's because Express is creating a req and res object for each request, none of which interfere with each other. But the res object associated with the /slow request is not deallocated because the callback (which is holding a reference to that instance) hasn't executed.

At the end of the day, I feel like you're overthinking things. It's good to understand the fundamentals, certainly, but for the most part, reference counting and garbage collection in JavaScript is not something you have to think about or manage.

I hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Ethan. Very nice detailed overview. Only if creators of modules would put forth such. My natural habitat is the embedded realm which makes me nosy. I like to know about potential trouble sources (things I shouldn't be doing) ahead of time instead of having to deal with them when they cause a bug. For example I just finished profiling/stress testing my code for memory leaks. Learned a lot from the endeavor ...
Heh, yes, I know what you mean. It is nice/important to understand the way things work (not just that they work). Even though most of the work I do today is high-level web work, the most fun I've ever had programming is doing embedded software. Viva la C!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.