Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The first step to understanding what is happening is understanding what's happening behind the scenes. From a language standpoint, there's nothing special about node modules. The 'magic' comes from how node loads files from disk when you <code>require</code>.</p> <p>When you call <code>require</code>, node either synchronously reads from disk or returns the module's cached exports object. When reading files, it follows <a href="http://nodejs.org/api/modules.html#modules_all_together">a set of somewhat complex rules</a> to determine exactly <em>which</em> file is read, but once it has a path:</p> <ol> <li>Check if <code>require.cache[moduleName]</code> exists. If it does, return that and STOP.</li> <li><code>code = fs.readFileSync(path)</code>.</li> <li><a href="https://github.com/joyent/node/blob/v0.10.5/src/node.js#L878-885">Wrap</a> (concatenate) <code>code</code> with the string <code>(function (exports, require, module, __filename, __dirname) {</code> ... <code>});</code></li> <li><p><code>eval</code> your wrapped code and invoke the anonymous wrapper function.</p> <pre><code>var module = { exports: {} }; eval(code)(module.exports, require, module, path, pathMinusFilename); </code></pre></li> <li><p>Save <code>module.exports</code> as <code>require.cache[moduleName]</code>.</p></li> </ol> <p>The next time you <code>require</code> the same module, node simply returns the cached <code>exports</code> object. (This is a very good thing, because the initial loading process is slow and synchronous.)</p> <p>So now you should be able to see:</p> <ul> <li>Top-level code in a module is only executed once.</li> <li>Since it is actually executed in an anonymous function: <ul> <li>'Global' variables aren't actually global (unless you explicitly assign to <code>global</code> or don't scope your variables with <code>var</code>)</li> <li>This is how a module gets a local scope.</li> </ul></li> </ul> <p>In your example, you <code>require</code> module <em>a</em> for each request, <em>but you're actually sharing the same module scope across all requrests</em> because of the module caching mechanism outlined above. Every call to <code>printName</code> shares the same <code>a</code> in its scope chain (even though <code>printName</code> itself gets a new scope on each invocation).</p> <p>Now in the literal code you have in your question, this doesn't matter: you set <code>a</code> and then use it on the very next line. Control never leaves <code>printName</code>, so the fact that <code>a</code> is shared is irrelevant. My guess is your real code looks more like:</p> <pre><code>var a; function printName(req, res) { //get param `name` from url; a = name; getSomethingFromRedis(function(result) { res.end('Hi '+a); }); } module.exports.printName = printName; </code></pre> <p>Here we have a problem because control <em>does</em> leave <code>printName</code>. The callback eventually fires, but another request changed <code>a</code> in the meantime.</p> <p>You probably want something more like this:</p> <p><strong>a.js</strong></p> <pre><code>module.exports = function A() { var a; function printName(req, res) { //get param `name` from url; a = name; res.end('Hi '+a); } return { printName: printName }; } </code></pre> <p><strong>index.js</strong></p> <pre><code>var A = require('a'); function requestListener(req, res) { var a = A(); a.printName(req, res); } </code></pre> <p>This way, you get a fresh and independent scope inside of <code>A</code> for each request.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload