2

I had two javascript files in Node Project. One was router which had routes and corresponding functions in it. Another was a utility class where commonly used functions are written as prototype. say utilservice.getSomething();

The first file calls utilservice.getSomething() in second file.

I imported the first file in second file (which is unnecessary and unused) .Then i called an API in first file.

I got error 500 stating utilservice.getSomething() is not a function.

I spent so much hours thinking something went wrong with use of Promise and tried with async and await and landed in same error.

Very last, i removed the import and found API call happening well.

I was with an impression that require is just for import of methods in another script. But there's something beyond it. There are resources online which would tell purpose of request. But i like to understand this behavior.

Sample:

File1.js

const utilService = require('../utils/utilService');

router.get('/something',function(req,res){
  utilService.getSomething().then((data)=>{
       //do something
 })
});

File2.js

const file = require('../file1');

function util(){}
util.prototype.getSomething = function(){
  return "hello"
}
module.exports = new util();

I hit that /something API. I got utilservice.getSomething is not a function.

Gayathri
  • 1,776
  • 5
  • 23
  • 50

3 Answers3

1

While require is usually used to import other modules and scripts, it also executes any code in these modules. This allows modules to overwrite properties of other modules and prototypes of objects. Modules don't require module.exports to be valid to be imported.

Ex:

File1.js

module.exports = {
  foo: ()=>{
    console.log("hello");
  }
};

File2.js

const mod = require("./File1.js");
delete mod.foo;

index.js

const mod = require("./File1.js");
mod.foo(); // hello
require("./File2.js"); // undefined
mod.foo(); // mod.foo is not a function
theusaf
  • 1,781
  • 1
  • 9
  • 19
  • Considering your file 2.js, atleast you did something with that file1 import. I did nothing with it. That import was totally unused. – Gayathri Aug 15 '20 at 16:32
1

Congrats, you have landed in the world of circular dependencies. Instead of just telling you what that is, I'll give you an example.

Say you had two files, file1.js and file2.js.
file1.js:

module.exports = {
  doSomething: function() {
    console.log("did something");
  }
};

file2.js:

const util = require("./file1");
util.doSomething();

file1.js exported a function called doSomething, and file2.js called it. So currently, the dependency tree looks like this:

file2.js -> requires -> file1.js

Now problems would start happening when you modify file1.js to this:

const file2 = require("./file2");
module.exports = {
  doSomething: function() {
    console.log("did something");
  }
};

Why? Well, let's look at the dependency tree now.

file2.js -> requires -> file1.js -> requires -> file2.js -> requires -> file1.js

See the problem? file2.js requires file1.js, which requires file2.js, but file2.js requires file1.js (etc, etc). Instead of getting stuck in an infinite loop, Node.JS loads the current state of module.exports from file1.js (which is undefined since the script got stuck on require("./file2")), and that's how you got the TypeError.

Take-Some-Bytes
  • 918
  • 1
  • 8
  • 21
  • Oh noooo! I didn't think about it. that's reasonable. Node terminal could have raised an error on server start stating there is such a problem with import, as it does when there's wrong directory structure in any of require or absence of any. Is there any lib in vscode which would raise such error before start ? It'll be helpful. Because, I was with an impression that anyway it is not being used so it won't do anything. – Gayathri Aug 16 '20 at 05:04
  • I just found this: https://www.npmjs.com/package/madge It may help. – Take-Some-Bytes Aug 16 '20 at 05:16
  • Still thinking how node server started in first place. – Gayathri Aug 16 '20 at 05:26
  • The server started because you didn't call the function when the server started. Since JavaScript doesn't throw an error when you try to reference an object's property that doesn't exist, the program starts fine. – Take-Some-Bytes Aug 16 '20 at 17:51
0

In nodeJS, require let you import modules from other files. It helps you split your application and only load necessary files to execute them, instead of having bunches of non used code loaded for nothing.

It actualy exists in many other languages under different names: require(php), include (php), import (typescript, python...etc)

One other thing: to be able to use require properly, you must "export" modules, definitions, functions, classes...etc to be able to use them in another script, using "module.exports" or "exports". So basicaly it has to do with "context", or if you prefer "scope".

This is why there's a folder named "node_modules" when you do a "npm install" using a package.json.

Thanks to "require", you can import only what is necessary, and not the whole project files every time you do something on your app.

millenion
  • 1,218
  • 12
  • 16
  • I export the method in file 2. And even the one I knew is thag require is to import from other modules so we can organize code instead of messing up with just one file having everything. Why did that unwanted import which is not even used anywhere inside made code break is what I wanted to know. – Gayathri Aug 15 '20 at 16:28