If so, that is an insane design.
If so, that is an insane design.
So you just don't use them and everything's good. Which brings you to the real problem: JavaScript makes it distressingly easy to use a global variable where you meant to use a local one.
> Global variables are basically instance variables on the
> process itself.
Not in JS. See my response to ww520 below.Seems like jesseedhillon was expecting that Node works like a browser: there's a lot of backend code in another language that handles the HTTP request, and then forks it over to a little JavaScript, and each request gets a new global scope.
It's not like that. There's a teeny bit of C-based backend code; it's the JavaScript part that controls alll the interesting stuff like opening sockets and parsing HTTP headers and the like to determine a request. In a single process, with a single global object, with lots of asynchronous I/O.
Node is JavaScript as a first-class programming language, not subservient to the DOM.
There is nothing other than a conscious design decision that forces the Node code that you write to run against the same global as the code that handles the I/O guts in Node...
In particular, you could have the code that listens on the socket and chunks up the byte stream into HTTP requests running against one global while all further processing of those requests runs against a different global or set of globals. It's just that Node chose not to do that. But that's not an inherent limitation of either JS the language or the V8 implementation.
All languages used in web server that don't spawn a new process for each request have the same feature.
It's trivial to have a single-process JS application with multiple JS global objects in it. Case in point: any web browser (and renderer processes don't change this: every iframe on a page has a separate global object).
It's just that Node _chose_ to reuse the same global object for multiple requests instead of using a clean execution environment.
I have to agree with jessedhillon: that sounds insane.
Even without doing this experiment, the result is obvious. There would have to be some meta process to start new interpreter processes here in order to prevent the same environment from being reused. Since that is not the case, because you have to invoke the python interpreter manually here, you cannot get multiple distinct results.
(Theoretically, in this code, you could get two different responses if they both entered the `if ... is None` clause in send_head() before one of the requests could cause the global variable to be set.)
In the case of Node, it's embedding V8. It can in fact run JS code of its choice in an environment of its choice, set up new globals, etc.
In practice, this problem is why you see `Array.isArray`, `jQuery.isArray`, `_.isArray` and friends so often -- they exist to give a canonical, non-"check if any member of X's inheritance chain matches Y.prototype" way to determine if a given instance is actually an array.
So, in summation: yes, it's weird that Node has this, but ultimately it's a lesser-vilified problem of JavaScript's.
[0]: https://github.com/joyent/node/blob/master/lib/module.js#L51 -- `NODE_MODULE_CONTEXTS=1 node <file.js>` will run separate modules in separate global contexts.
Happily, this is all changing--in the long run, future versions of JavaScript should polish away these issues while maintaining the fundamentally sound core of the language. In the short run "use strict" lets you realize some of the upcoming improvements in otherwise legacy code.
In my opinion it wouldn't be quite as scary if js didn't make it so damn simple to accidentally define a global variable (like in this instance, where it was never actually declared in globally-scoped code).
When dealing with true multi-threading you have all sorts of issues you need to worry about, like locking for writing, worrying about deadlocks, etc. that make coding much more difficult.
If you did take advantage of the runtime's support for multiple global objects, what would those global objects correspond to? The most natural scope would be "user session" - but if you go that route, now you support stateful user sessions. And before you know it you have developers storing loads of user session state in the server's RAM and wondering why they keep running out - and lose the ability to easily fail over to another server process.
So I imagine Node's author decided it was better to just keep things simple and discourage use of globals.
But doing global per request would not be that complicated, if desired.