NodeJS: module.exports property is not a function - javascript

I have the following in a module file:
module.exports = {
myfunc: myfunc
};
var myfunc = function(callback){
callback(err,reply);
};
In an other file I got the reference to that module
var mymodule = require('./modules/mymodule');
mymodule.myfunc(function(err, reply){ ... });
When I call the mymodule.myfunc() I get an error saying "property 'myfunc' is not a function".
This happens only with exported functions. The same module exports some 'string' fields and these are working just fine.

When you assign module.exports, the myfunc function is still undefined. Try to assign it after declaring it:
var myfunc = function(callback){
callback(err,reply);
};
module.exports = {
myfunc: myfunc
};

To preserve your original ordering of module.exports at the top of your file, change your var myfunc initialization to a function myfunc declaration so that the latter is hoisted.
module.exports = {
myfunc: myfunc
};
function myfunc(callback){
callback(err,reply);
};
Declarations are hoisted, but initializations are not, which is why your original example did not work. w3schools has a practical description of JavaScript Hoisting.

Another scenario where i found this annoying issue was if explicitly imported only the function that my consumer needs
Say for example your exported modules looks like below
module.exports = {
func1 : async function func1(){}
func2 : async function func2(){
await this.func1(); // causes error : func1 is not a function
}
}
Now your consumer of above module looks like below:
const { func2 } = require('../theExportedModules');
//above only imports func2 but not its dependents and is not initialized
await func2(); //func2 called
Now func2() gets called from your consumer but func2() will not be able to call the func1() because it finds that func1() is not a function. Code breaks!
solution import entire modules:
const theExportedModules = require('../theExportedModules');
we could also just import func1 as well but then it would be an unused variable and we would get a warning for that.

Related

Imported module function in app.js does not have access to class instantiation or app.js variables. Javascript node

I have working code that fails when I try to split it into modules, this is a super simplified version to highlight the behavior I don't understand.
When app.js runs, there is a 'ReferenceError: elf1 is not defined'. I do not understand why func1 does not have access to elf1. I thought maybe changing the func1 to an arrow function away from a standard function would make func1 lexically scoped to app.js.
I realize that in App.js I can declare global.elf1 = new Elf() and then func1.js will have access. However, I don't understand why when an arrow function in a module is invoked within the app.js environment it doesn't have access to the app.js variable environment.
I'm sure this is simple and I'm overlooking some obvious behavior, I thought func1 being an arrow function would have access to app.js environment variables since it was invoked in app.js.
//App.js
let Elf = require('./class');
let func1 = require('./func');
var elf1 = new Elf('jim');
func1();
---------------------------------------
//class.js
class Elf{
constructor(name){
this.name = name;
}
shout(){
console.log(`my name is ${this.name}`);
}
}
module.exports = Elf;
----------------------------------
//func.js
let func1 = ()=>{
elf1.shout()
}
module.exports = func1;
func.js has no idea what elf1 is because it's outside of the module scope.
I would just pass in elf1 as a parameter into the func1 function.
//App.js
let Elf = require('./class');
let func1 = require('./func');
var elf1 = new Elf('jim');
func1(elf1);
//func.js
let func1 = (elf1)=>{
elf1.shout()
}
module.exports = func1;

Calling functions from a parameterized module.exports

Referencing this solution, I need to pass a parameter into module.exports of my utils.js file.
// utils.js
var module;
module.exports = function (name) {
if (module) return module;
module = {};
module.sayHi = function () {
return `Hi, ${name}`;
};
return module;
};
I'm a bit confused as to how to call sayHi after requireing utils.js.
// index.js
const utils = require("./utils")("Jim");
utils.sayHi();
I'm getting TypeError: utils.sayHi is not a function. What's the right way to call sayHi?
First you create a variable named module.
var module;
This does nothing because you are doing this in the scope of the module, so that variable already exists.
Then you assign a function to module.exports.
In another module, you import that function and call it.
The first line of that function says:
if (module) return module;
Is module a truthy value?
Yes. It is an object. If it wasn't, then assigning to module.exports would have throw an exception.
Consequently, you never overwrite module = {}; or assign the sayHi function to it.
Now look at the answer you referenced:
module.exports = function (app, db) {
var module = {};
It creates a new variable in the scope of the function so it doesn't conflict with the existing one.

Module functions appear undefined in outside scripts

This code tells me that the parse function is not a function:
const MyModule = require('./MyModule.js');
MyModule.parse('...');
In my module script it's defined like this:
MyModule = {};
MyModule.parse = function(data){
};
module.exports.MyModule = MyModule;
What am I doing wrong?
You have to understand that you are not exporting MyModule but an object (module.exports to be exact) with a member called MyModule (this is what you assigned to it).
If, in your code that requires MyModule, you console.log the result of your require, it will look like:
{ MyModule: {parse: [Function] } }
which is the module.exports object with a property (object) called MyModule that has a property (function) called parse.
So when you require you are getting the module.exports object that you assigned MyModule to and not just MyModule.
If you were to change your module.exports code to:
module.exports.X = MyModule;
Your code that required MyModule would then log:
{ X: {parse: [Function] } }
and you would call it as
MyModule.X.parse(...).
If you then changed your code to read
const MyFabulousModule = require('./MyModule');
you would then call it like:
MyFabulousModule.X.parse(...);
Finally, if you added another line to your module:
module.exports.Y = 4;
And then in your calling code added:
console.log(MyFabulouseModule.Y);
you would see the value 4 logged to the console.
Code:
MyModule.js
const MyModule = {};
MyModule.parse = function(data) {
console.log(data);
};
module.exports.X = MyModule;
module.exports.Y = 4;
test.js
const MyModule = require("./MyModule");
console.log(MyModule);
MyModule.X.parse("hello world");
console.log(MyModule.Y);
To run: node test.js
First of all, you need to add a keyword in definition object.
const MyModule = {};
And you export the object, which you appoint to constant, so you need to call the object from it like this:
MyModule.MyModule.parse('...')

Calling local functions in node.js

js files index.js and utils.js
I have tried to do the module export solution with no luck.
To call a function in utils.js from index.js I write a the function in utils as
export.functioname = function(parms) {
...
};
If i want to call the same function internally from utils.js i can do it i have to write another identical function as:
var functionname (parms) {
...
}
How can i get around this and only have one function to be called externally and internally?
You can use:
var yourfunction = function(param){
console.log(param);
}
exports.yourfunction = yourfunction;
yourfunction("Works");
Which prints:
"Works"
Functions can be saved to variables
var moo = function(parms) {};
export.functioname = moo;
or
function moo(parms) {};
export.functioname = moo;
works aswell because of js closures

How to properly require a node module, exporting all the functions in it

I have a file stats.js.
It's contents are
(function () {
func1 = function () {
}
func2 = function () {
}
module.exports = this;
}).call(this);
Alegedly, when I do
var stats = require("./stats");
I should be able to get func1 and func2 with stats.func1, stats.func2, right?
Well, I can't. The stats object is just empty. A few traces in the stats.js revealed that "this" is also an empty object.
What gives?
First and foremost see this link.
Now lets see your code -
var stats = require("./stats");
//My steps -
//First Log
console.log(stats.func1); // returns undefined
//Second Log
console.log(global.func1, global === GLOBAL); // returns [Function], true
Take aways from this code -
1. In the browser the global object is window object.
2. In node.js it is the global object.
3. Defining something using var in a module will only create a variable with a module scope.
4. Defining something without the var keyword will create a variable in the global scope.
So func1 and func2 were defined in the global scope. Passing this to module.exports will pass the current module object only.
hope it helps, happy coding!
No it shouldnt? That format is nothing like what Node.js needs in order to do its job.
"What gives" is that you didn't read up on how node works. Node.js isn't just "JavaScript", it's a proramming model with a much richer API and specific behaviours. Requires use the "module.exports" object, so it would be a good idea to actually read up on how to use node.
mything.js:
var func3 = function() { ... },
prop = "something";
...
module.exports = {
func1: function() { ... },
func2: function() { ... },
func3: funct3,
prop: prop,
...
};
which is identical to:
var func3 = function() { ... },
prop = "something",
...
MyLib = {
func1: function() { ... },
func2: function() { ... },
func3: funct3,
prop: prop,
...
};
...
module.exports = MyLib;
app.js:
var mything = require("mything);

Categories