NodeJS required module not available in other modules - node.js

I'm a bit new to NodeJS. Maybe it's just the way it works but to be sure:
My 'index.js':
var fs = require('fs');
// do something with fs here
var app = require('./app.js');
The 'app.js'
fs.readFile('/somedir/somefile.txt', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
console.log(data);
});
Then I get an error:
ReferenceError: fs is not defined
As I've read, the 'solution' to this is to 're-require' the fs-module in app.js. Now what I do understand is that the fs-module is cached (any module, but using the example) so Node will still be really quick. What I don't really get is: "If the fs-module is cached, so actually it's kinda available anyway, why do I still have to 're-require' the module?
I'll be honest; it's just to understand why.

Each file has to include references to modules
index.js
var fs = require("fs"),
other = require("./otherfile");
// you can now use `fs`
otherfile.js
var fs = require("fs");
// you can now use `fs` here
One of the best parts about this is you're not locked into naming the variable a certain way in any given file. Every file is pretty much isolated from all the other files in your lib, and that's a very good thing.
Also know that you can include just parts a module if you'd like
var read = require("fs").readFile;
read("myfile.txt", function(err, data) {
if (error) {
return throw error;
}
console.log(data);
};
Explanation:
Node.js does not encourage the use of globals; and as such, you should not try to implement things that depend on global variables.
When you call in the fs module again, it's not really "re-requiring" it so much as you're just declaring a variable that points to the cached module.
Additional example:
In this answer I go into detail about how to structure a simple app that avoids the use of globals.

Sometimes we can forget it, but it's fundamental to declare it:
var fs = require('fs');

Related

I get require is not defined error if I call it from external files

Hi,
I made an app for node.js so my app.js looks like this:
global.fs = require("fs");
global.vm = require('vm');
var includefile = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
}.bind(this);
includefile("variables.js");
as for variables.js I have this:
global.app = require("express")();
but when I start the app I get this error:
require is not defined at variables.js
why is it that requires loads fine if executed from app.js but not from an external file?
Thank you.
I'm a little confused, is variables.js just another source file in your project? All you should need to do is require the file in like you've done at the top. As an example for variables.js:
const Variables = {
fs: "some_value"
};
module.exports = Variables;
And for app.js
const { Variables } = require("./variables.js");
const fs = Variables.fs;
Executing console.log(fs); in app.js will print "some_value". Same can be done with functions.
If variables.js is part of your project code, you should use the answer of M. Gercz.
If it's not part of your project code and you want to get some information from it, you could use a json file:
app.js
const variables = require('variables.json');
console.log(variables.whatever);
variables.json
{ whatever: "valuable information" }
If it's not certain, that variables.json is preset, you can do a check using fs.existsSync;
Notice: As jfriend00 commented, using global is not recommended.

Is there any way how to modify file during the require?

I would like to modify code of library like inject some custom "code" during the require.
Example:
const fs = require('fs');
const file = fs.readFileSync('./in').toString();
console.log(file)
So, I would like to modify function readFileSync from fs module. Is there any way how to inject console.log('hi') into readFileSync function and how?
This is commonly known as the Decorator pattern. In short, you'd take the function and wrap it in another function that does something else plus the original behavior.
Example:
const fs = require('fs');
function myReadFileSync(...args) {
// If you want the console.log before:
console.log('will read file');
fs.readFileSync.call(fs, ...args);
// If you want a log after the real operation:
console.log('managed to read the file');
// (of course, you can have them both as well)
}
Then, use myReadFileSync instead of the original. This can usually be accomplished using Dependency injection - you can inject functions just as well as you could inject objects as dependencies.
If the idea is to modify the "real" fs module, don't. This is an anti-pattern where you pollute the global namespace by altering default behaviors that the code relies on. It can be done in Node.js, but should only be undertaken if you know the consequences for your code. This is also a problem with some testing libraries such as Jest - they modify global objects, which is generally inadvisable.
Having said that, here's how apply this technique, which is called monkey patching:
const fs = require('fs');
// We need to preserve the original implementation somewhere:
const realReadFileSync = fs.readFileSync;
fs.readFileSync = function myReadFileSync(...args) {
// Same as in the decorator:
realReadFileSync.call(fs, ...args);
};
It's best to read about it, evaluate the pros and cons, and decide whether this is what you want in your codebase.

node.js share dynamic variables between modules

I have a variable named number_of_clusters which must be updated periodically. number_of_clusters must also be shared with other modules to read it. how can I assure that reading modules will read a fresh copy of this variable each time they access that?
I dont want to use database to share this variable so I thought I could share it via process.env
process.env.number_of_clusters = 1;
is it a good practice?
Seems like your searching for a global variable:
global. number_of_clusters = 1
However using a database or a file would probably be a nicer solution.
Try reading/writing in a file?
var fs = require('fs');
fs.writeFile("/path/to/file", "whatever", function(err) {
console.log("The file was saved!");
});
fs.readFile('/path/to/file', 'utf8', function(err, contents) {
console.log(contents); // -> whatever
});
If the other modules are running as part of the same Nodejs process,
you can just export a getter to other modules which will get the fresh value of number_of_clusters for them.
Like:
function get_number_of_clusters() {
return number_of_clusters;
}
module.exports = { get_number_of_clusters };
Now in other modules, you need to import this module and call this method, like:
var getter = require('path/to/above/module').get_number_of_clusters;
var number_of_clusters = getter();
You could use socket.io to store the variable on the server and have it emit to all pages.

Are node.js modules need to be wrapped inside the module pattern?

To ensure proper isolation, I tend to wrap each node.js module that I write inside a function scope:
(function() {
var express = require('express');
var jade = require('jade');
var moment = require('moment');
exports.someFunction = function() {
// do something
};
exports.otherFunction = function() {
// do something else
};
})();
I've been doing this for some time now, but I have the feeling that node.js' module system is actually doing this for me, or (in other words) that the above code is equivalent to the following code:
var express = require('express');
var jade = require('jade');
var moment = require('moment');
exports.someFunction = function() {
// do something
};
exports.otherFunction = function() {
// do something else
};
Are the two really equivalent?
In particular, I am interested to know whether is the isolation level is the same: are the express, jade or moment variables local to the module? (i.e., I'd like to make sure that they are not defined in the global scope or interfere with any other definition outside of this module).
Variables declared within a module are local to that module. It is safe to omit your enclosing function.
From the Node.js docs:
Variables local to the module will be private, as though the module was wrapped in a function

Node.JS - fs.exists not working?

I'm a beginner in Node.js, and was having trouble with this piece of code.
var fs = require('fs');
Framework.Router = function() {
this.run = function(req, res) {
fs.exists(global.info.controller_file, function(exists) {
if (exists) {
// Here's the problem
res.writeHead(200, {'Content-Type':'text/html'});
var cname = App.ucfirst(global.info.controller)+'Controller';
var c = require(global.info.controller_file);
var c = new App[cname]();
var action = global.info.action;
c[action].apply(global.info.action, global.info.params);
res.end();
} else {
App.notFound();
return false;
}
});
}
};
The problem lies in the part after checking if the 'global.info.controller_file' exists, I can't seem to get the code to work properly inside the: if (exists) { ... NOT WORKING }
I tried logging out the values for all the variables in that section, and they have their expected values, however the line: c[action].apply(global.info.action, global.info.params);
is not running as expected. It is supposed to call a function in the controller_file and is supposed to do a simple res.write('hello world');. I wasn't having this problem before I started checking for the file using fs.exists. Everything inside the if statement, worked perfectly fine before this check.
Why is the code not running as expected? Why does the request just time out?
Does it have something to do with the whole synchronous vs asynchronous thing? (Sorry, I'm a complete beginner)
Thank you
Like others have commented, I would suggest you rewrite your code to bring it more in-line with the Node.js design patterns, then see if your problem still exists. In the meantime, here's something which may help:
The advice about not using require dynamically at "run time" should be heeded, and calling fs.exists() on every request is tremendously wasteful. However, say you want to load all *.js files in a directory (perhaps a "controllers" directory). This is best accomplished using an index.js file.
For example, save the following as app/controllers/index.js
var fs = require('fs');
var files = fs.readdirSync(__dirname);
var dotJs = /\.js$/;
for (var i in files) {
if (files[i] !== 'index.js' && dotJs.test(files[i]))
exports[files[i].replace(dotJs, '')] = require('./' + files[i]);
}
Then, at the start of app/router.js, add:
var controllers = require('./controllers');
Now you can access the app/controllers/test.js module by using controllers.test. So, instead of:
fs.exists(controllerFile, function (exists) {
if (exists) {
...
}
});
simply:
if (controllers[controllerName]) {
...
}
This way you can retain the dynamic functionality you desire without unnecessary disk IO.

Resources