2

I am using NodeJS. Is it possible to require a javascript file in node as we do in browsers? Because when I use the require() method it calls a javascript file that as no access to the global variables in my server.js it is like a "use strict" I guess. I needed to load my module and make it a continuation of the main file since my module depends on some global variables.

EDIT:

I have this server.js file:

var Settings = require("settings.js");
var Clients = require("clients.js");
var removePack = [];

/**HERE RUNS MY WEBSOCKET SERVER**/
...
...
//When a new socket connects:
io.on("connection", function(socket){
    var socket.id = Math.random();
    var client = Clients.create(socket.id);
});

Here my clients.js file:

exports.create = function(){
    self.team = Settings.generateRandomTeam(); /*The problem is here. I can´t access the Settings variable*/
    self.maxSpeed = Settings.maxSpeed;
    ...
    ...
    return self;
}

EDIT 2:

When I use Settings = require("settings.js") I get the following error:

TypeError: Settings.generateRandomTeam() is not a function.

My settings.js file is like this:

Settings.generateRandomTeam = function(){
   //Some code
}

module.exports = Settings;

Thanks!

Daniel Oliveira
  • 1,280
  • 14
  • 36
  • 1
    You just do `var foo = require('foo.js');`. Make sure to export what you want to access – Andrew Li Aug 29 '16 at 01:06
  • Make sure you use the right path! If you require your file like `var foo = require('foo.js');` - This is trying to require a global module on your computer. Try `var foo = require('./foo.js');` – James111 Aug 29 '16 at 01:09
  • 3
    First off, in node.js don't ever think about using global variables (99.9999% or the time they are not needed or appropriate). You need to learn how modules in node.js work and how to share data among modules. Hint: using globals is NOT the way to do things in node.js. You can use a push or pull model to share. The simplest way is to call a module constructor and pass it the data you want to share which I refer to as the "push" model since you're pushing data to the other module to share. – jfriend00 Aug 29 '16 at 01:09
  • Hello jfriend00. I think you hit the point. Can you explain me or send a good tutorial about pushing or pull data between node modules? Because I have modules that depend on other modules. I search on google before asking here but I did not find much. – Daniel Oliveira Aug 29 '16 at 01:18
  • 1
    This site works a lot better if you show us the code you have for two modules and explain what you want to share between them and we can show you exactly how to solve that problem. Without that, we have to come up with a generic tutorial on sharing data between modules which is both a lot more for us to write and it only has about a 30% chance of actually covering what you want. So, please be more specific in your question and include code from your two modules that shows what you want to share and which module is likely to be loaded first. – jfriend00 Aug 29 '16 at 01:21
  • Some examples of module sharing: [The Fundamentals of the Node.js Module Paradigm?](http://stackoverflow.com/questions/26694961/the-fundamentals-of-the-node-js-module-paradigm/26695038#26695038), [Global Variables Alternative](http://stackoverflow.com/questions/34862600/global-variables-alternative/34862722#34862722), [Is it a good idea to load everything into one object in Node.js](http://stackoverflow.com/questions/26415435/is-it-a-good-idea-to-load-everything-in-to-one-variable-in-node-js/26415564#26415564). – jfriend00 Aug 29 '16 at 01:26
  • And,a couple more: [Access variable in main node file from an imported file](http://stackoverflow.com/questions/36749168/access-variable-in-main-node-file-from-an-imported-file/36749357#36749357), [How can i export socket.io into other modules in nodejs?](http://stackoverflow.com/questions/38511976/how-can-i-export-socket-io-into-other-modules-in-nodejs/38514118#38514118). – jfriend00 Aug 29 '16 at 01:30
  • On an unrelated note, `socket.id = Math.random()`? I guess it will almost always work, but why not use a simple counter? That would still generate unique IDs, as JS is single-threaded. – qxz Aug 29 '16 at 01:43
  • OK, now that you've shown the code, what exactly is the problem? Other than getting rid of `socket.id = Math.random()` because `socket.id` is already defined by socket.io to be a unique id value, I don't know what problem you have. You look like you are already bring clients.js into the server.js just fine. Also, this is probably a typo because `var socket.id = Math.random();` would be an error because of the `var`. – jfriend00 Aug 29 '16 at 01:44
  • Yes I did, but in my clients.js I use data from my settings.js file and I can´t access that data. – Daniel Oliveira Aug 29 '16 at 01:46
  • Just do `var Settings = require("settings.js");` inside your `clients.js` file. `settings.js` is meant to be shared. Any module that wants those settings should just `require()` it in by themselves. You don't need someone else to load it for you and then share it from them. If you need it, just `require()` it in. Modules are cached so it won't actually even load again. – jfriend00 Aug 29 '16 at 01:46
  • Will that reload the module? – qxz Aug 29 '16 at 01:47
  • No. Modules coming from the exact same path are cached. – jfriend00 Aug 29 '16 at 01:47
  • So it will return the same object, right? – qxz Aug 29 '16 at 01:48
  • Yes, same object. – jfriend00 Aug 29 '16 at 01:48
  • When we do something like var foo = require('foo.js'); then we are asking for a hard coded file name 'foo.js'. Is there a way to ask for foo.js in a safer way where if we rename foo.js to bar.js we won't get problems? – Sachin Kainth Dec 22 '16 at 13:42

1 Answers1

2

To get access to the Settings object from the clients.js file, just add this to your clients.js file:

const Settings = require("settings.js");

exports.create = function(){
    self.team = Settings.generateRandomTeam(); /*The problem is here. I can´t access the Settings variable*/
    self.maxSpeed = Settings.maxSpeed;
    ...
    ...
    return self;
}

Modules in node.js are cached so two require() statements that resolve to the exact same file path will return the exact same cached module. So, because of the caching, you will actually get the same Settings object each time you call require("settings.js").

This is a key to sharing in node.js. You don't think about loading something once and then trying to share that everywhere. Instead, you think about having each module require() in what it needs (when possible). This promotes the independence and reusability of your modules as they tend to be more stand-alone useful rather than depending upon some global environment that's already been built for them.

There are, of course, other ways to share data by pushing data to a module in a module constructor function or pulling data by having a module call out to other modules when it loads to retrieve data from them. This may be necessary in some cases when a module needs to be given a specific instance of something (like a database handle).

Drew
  • 1,687
  • 5
  • 25
  • 46
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • @DanielOliveira - Where is `settings.js`? If it's in the same directory as `clients.js`, then you would load it with `require('./settings.js')`. – jfriend00 Aug 29 '16 at 02:02
  • No it is on the root directory. – Daniel Oliveira Aug 29 '16 at 02:18
  • But I had to include the file clients.js in the settings.js file. I also included the settings.js in the client.js file because both depend on each other. Is this creating an infinite require loop and maybe creating this problem? – Daniel Oliveira Aug 29 '16 at 02:19
  • I tried to save the Settings.js with the name Settings2.js and use require("/Settings2.js") and it worked. This is so weird. – Daniel Oliveira Aug 29 '16 at 02:25
  • 1
    @DanielOliveira - This just sounds like path or permission issues. `require()` just needs a valid path to a file that node.js has permissions to read and, of course, the JS file needs to be in the proper format to be a node.js module. – jfriend00 Aug 29 '16 at 03:50
  • 1
    @DanielOliveira - Did this answer your question? If so, you can indicate that to the community by clicking the green checkmark to the left of it. If it didn't answer your original question, then please explain what part of the original question is not answered yet. – jfriend00 Aug 29 '16 at 05:22