6

I know using the global variable is discouraged in node, but assuming I need to store some data globally, which is a worse approach:

  1. using global

  2. Using the require cache directly to store an object, i.e.

    require.cache["myGlobalVar"] == {};

I suspect that option 2 is worse because the require cache is intended to be used for modules.

More details: I thought about using require("myLibrary").myGlobalVar but that would require having myLibrary accessible to all the files calling it, which might not be possible in practice. I'm making a code coverage tool so I can expect the user to install "myLibrary" in their dev/test modules, but not necessarily in their src node_modules directory, to which the instrumented code files would refer.

3 Answers 3

14

Why don't you just create an in memory cache that all of your other code can then reference?

var memoryCache = module.exports = function () {
    var cache = {};
    return {
        get: function (key) { return cache[key]; },
        set: function (key, val) { cache[key] = val; }
    }
}

You can then use the cache from any place by require'ing it.

var cache = require('../cache/memoryCache')();
cache.set('1234', 'value I want to share');
cache.get('1234');  // 'value I want to share'
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for the quick reply. The problem with that approach (since it's similar to just using require("myLibrary") is that I'm instrumenting code for code coverage. So I will be take src files, adding extra lines of code, and then saving the modified copies. Using require to reference a local file like this would entail adjusting all the relative paths in the require statements to point to the correct file. While it's not impossible, it could be messy.
People solve this problem by using index.js files which point to the appropriate version of files when doing code coverage builds. Every file then references the index.js file which exports the appropriate version of the references. This way you don't have to change any of the require statements. Take a look at github.com/visionmedia/express/blob/master/index.js as an example.
The index.js of the code coverage tool itself? I thought about that, but if the person has separate node_modules for their tests and for their src then it will fail, unless they install the coverage tool in their src node_modules folder, no? i.e. /test /node_modules/cover/index.js runner.js - calls the instrument library /src /node_modules srcfiles.js in this case referencing index.js from srcfiles.js wouldn't work, I would think.
I think the example from express just remaps the source files to the instrumented files. Mocha (used to run the express tests) uses the global node variable, if my memory serves me, I was just looking for alternatives for that method because I understood that using the global variable was not recommended. github.com/visionmedia/mocha/blob/master/lib/reporters/…
I'm confused, code coverage in Node is a solved problem. A tool is used to instrument the code and dump it into a folder. Code developers use an index.js file to switch between the different versions (instrumented or not). Tests are run and code coverage data is collected. See tjholowaychuk.com/post/18175682663/mocha-test-coverage. Why wouldn't you follow a similar process?
|
13

The answer from Bill didn't work for me because it can in fact not be used "from any place by require'ing it". This is because it's exporting a function that is called on each require and thus creating a blank new (empty) cache each time.

The solution is exporting an instance of the function...

// cache/memoryCache.js
module.exports = function () {
    var cache = {};
    return {
        get: function (key) { return cache[key]; },
        set: function (key, val) { cache[key] = val; }
    }
}();

...and then requiring that very instance each time.

// some other file
var cache = require('../cache/memoryCache');
cache.set('1234', 'value I want to share');
cache.get('1234');  // 'value I want to share'

(Note the difference: the pair of parenthesis "()" is now at the end of the function definition in the module and not after the require.)

Comments

1

Every time, when you require cache file, it will trigger the function again and initialize the cache object again.

var cache = {}

to solve this we can implement the cache like mentioned below:

//cache.js
module.exports = {
    cache: {},
    get: function (key) { return this.cache[key]; },
    set: function (key, val) { this.cache[key] = val; },
    dumpCache: function () { return this.cache } // this just for testing purpose
}
// index.js

var cache = require('./cache');

cache.set('12', 'Hey');
console.log(cache.get('12'));
console.log(cache.dumpCache());

Comments

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.