This question already has answers here:
What is the purpose of Node.js module.exports and how do you use it?
(13 answers)
Closed 7 years ago.
Say I have the following module makeDir which checks for the existence of a directory and creates one if it does not exist or simply calls its callback with null if the directory already exists.
Which would be the proper way to export this module?
module.exports = makeDir or module.exports.makeDir = makeDir ?
'use strict';
var fs = require('fs');
var mkdirp = require('mkdirp');
var makeDir = {};
makeDir.handler = function (dstPath, sizesObj, callback) {
var _path = dstPath + sizesObj.name + "/";
fs.lstat(_path, function (err, stats) {
if (err) {
mkdirp(_path, function (err, made) {
if (err) {
console.log("Error creating directory: %s", err);
callback (err, null);
} else {
console.log("Created new directory");
callback(null, made);
}
});
} else {
callback(null);
}
});
};
module.exports = makeDir;
Both methods of using module.exports or module.exports.FUNCTION_NAME are okay but the difference comes when you require these functions.
Let me show the difference using an Example.
a. Assigning function directly to module.exports
// mkdir.js
module.exports = function(){
console.log("make directory function");
};
// app.js
var mkdir = require("mkdir.js");
mkdir(); // prints make directory function
b. Exporting function at property in module.exports
// mkdir.js
module.exports.first = function(){
console.log('make directory function');
};
// app.js
var mkdir = require('mkdir.js');
mkdir.mkdir(); // make directory function
Hope it helps!
module.exports = makeDir;
is the correct method if you are exporting only one object from javascript file.
IN CASE YOU NEED TO EXPORT MORE THAN ONE OBJECTS
var makeDir = {
obj1 : function(){},
obj2 : function(){}
}
module.exports = makeDir;
This way you can use makeDir.obj1 and makeDir.obj2 in other file.
Related
How do I call the function expression "extractUserProgress" which is situated in an external module from server.js?
EDIT
I have clarified further what is happening in my code.
I have a chain of function expressions in my module that follow from "extractUserProgress". The last function returns an array which is what I'm after.
//setGen.js (module file)
module.exports = function(app, db) {
var extractUserProgress = function() {
//Access mongoDB and do stuff
nextFunction(x)
}
var nextFunction = function(x) {
let y = [];
//calculate y
return y // this is what i'm after
}
}
//server.js
const setGen = require("./setGen")
app.get("/setGen", function(req, res){
//data here from select input
extractUserProgress //How to call from here?
console.log(y) //array from module
});
I have required the module in server.js but not sure how to export function in this scenario where the functions in module also needs to access mongoDB.
Thanks
You can achieve this easily if you change the structure of your exports a little.
const extractUserProgress = function (app, db) {
console.log('This can be called');
//Access mongoDB and do stuff
}
module.exports = {
extractUserProgress
};
you can call this function from the otherside this way.
const newFile = require('./server');
newFile.extractUserProgress(); // you can pass arguments APP and DB to this function
With the code as-is, you can't - extractUserProgress is not accessible, it's declared inside the exported function scope.
If you need it accessible, and also need to keep the exported signature, then you can return a hash of functions e.g.
module.exports = function(app, db) {
...
return {
extractUserProgress(...) {
...
},
// More functions
}
}
// Usage
const setGen = require('./setGen')(app, db)
setGen.extractUserProgress(...);
If you don't need to maintain the existing exported function, then you can export the functions as a hash instead
module.exports = {
extractUserProgress(...) {
...
},
// More functions
}
// Usage
const setGen = require('./setGen')
setGen.extractUserProgress(...);
I am trying to facilitate and organize my work between socket communication and Node.JS (My project is too big)
Instead of socket.emit() function in client-side I use a function that I created:
function socketEmit(socketName, functionName, data){
socket.emit(socketName, {functionName: functionName, data: data});
}
socketEmit('exampleClass', 'exampleFunction', 'test');
socketEmit('exampleClass2', 'exampleFunction2', 'test');
After emit, I get the socket (socket.on) on the server-side with this function. And register it in the class depending on the "socketName"
socket.on('exampleClass', function (socketData){
var exampleClass = require('./server/exampleClass.js');
exampleClass.registerSocket(socket, socketData);
})
socket.on('exampleClass2', function (socketData){
var exampleClass2 = require('./server/exampleClass2.js');
exampleClass2.registerSocket(socket, socketData);
})
Within the classes has this function "registerSocket" to perform the same
exampleClass.js
module.exports = {
registerSocket: function(socket, socketData){
var functionName = socketData.functionName;
var data = socketData.data;
[functionName](socket, data);
},
}
function exampleFunction(socket, data){
console.log('test');
}
However, I have an error in this part in registerSocket function:
[functionName] is not a function
You're trying to call a an array [functionName](socket, data);:
const array = [functionName]; // array
array(socket, data); // you can't :)
Put the functions in an object, and access it using [] notation.
const fns = {
exampleFunction(socket, data){
console.log('test');
}
};
module.exports = {
registerSocket: function(socket, socketData){
var functionName = socketData.functionName;
var data = socketData.data;
fns[functionName](socket, data);
},
}
that is my db.js from where i am exporting the function
var mysql=require('mysql');
var config=
{
host:'127.0.0.1',
user:'root',
password:'',
database:'travel'
};
var con="";
var data=function getConnection()
{
con=mysql.createConnection(config);
con.connect(function(err)
{
if(err!=null)
{
console.log('connection id: '+con.threadId);
}
else
{
console.log('connection error: '+err.stack);
}
})
};
module.exports=data;
and here is my login.js file from where i am calling that exported data function
var express=require('express');
var db = require.main.require('./model/db');
var router=express.Router();
//routes
router.post('/',function(req,res)
{
console.log(req.body);
});
router.get('/',function(req,res)
{
data();
res.render('login');
});
module.exports = router;
Here is the error message after running the code. can anyone please help me with that problem?
You should change the import statement as follows, because you are invoking the data() not db(). so you should change the import statement to data instead of db
var data = require.main.require('./model/db');
When you use module.exports you're specifying the object that is exported, not a name or set of names. Since you literally just export the data function you want to use, the line var db = require.main.require('./model/db'); first creates/finds that function and then assigns it to the variable db -- the original name doesn't matter at all.
Possible solutions to that problem (as indicated in the other answers) include replacing data() with db() or replacing var db with var data.
I am using the EJS compile to create notification templates and I would like to know how to write the file to the file system in parallel and send the notification once all the files are saved.
Please see the below code snippet which I used
var fs = require('fs');
var ejs = require('ejs');
var arrayOfData = [someData]; //Prepare data from database
//Iterate through the data
for (var i = 0; i < arrayOfData.length; i++) {
generateFileFromTemplate(arrayOfData[i],function(){});
}
function generateFileFromTemplate(templateData,callback)
{
var outputFile = fileData.Id + ".html";
var compiled = ejs.compile(fs.readFileSync('email-template.ejs', 'utf8'));
var html = compiled(templateData);
fs.writeFile(outputFile, html, callback);
}
Please help.
Use async.each for your use case
async.each(arrayOfData,
function(ele, next){
generateFileFromTemplate(ele,function(){});
},
function(err){
if(err) console.log('err', err);
sendNotification();
}
);
You can use a great utility library called Async, particularly its parallel method: https://github.com/caolan/async#parallel.
Here's an example:
var async = require('async');
/*-------------*/
var tasks = arrayOfData.map(function(data) {
return function(cb) {
generateFileFromTemplate(data,function(){});
cb(null);
}
});
async.parallel(tasks, function(err) {
console.log('My job is done');
})
I've been looking around for a few days not and really I feel like I'm missing a part of the concept here... I'm fairly new with node.js, and I'm trying to call a method from a different module in my main class per-say...
Here is the code..
inputReader.js
(function() {
var dir = './views/'; // Declare the directory to be scanned
var data = {} // Create array object for storage
fs.readdir(dir, function(err, files) {
if (err) {
throw err;
}
var c = 0; // Declare a var c = 0; initial condition of a for loop
files.forEach(function(file) {
c++; // Increment a counter in the for-loop condition
fs.readFile(dir+file, 'utf-8', function(err, string) {
if (err) {
throw err;
}
if ( 0 === -3) {
data[file] = string; // Throws into data object string of contents within the file being read
console.log(data); // We only need this to test using console (the contents being stored)
}
});
});
});
module.exports.getData = function() {
return data();
}
}());
And here is how I'm trying to call it in app.js
var inputReader = require('./inputReader').inputReader;
app.get('/', function(req, res){
res.send(inputReader.getData());
});
app.listen(3000);
console.log('Listening on port 3000');
My prediction for if I did this correctly, my localhost page would display the contents of the files within the folder I designated the app to read; ./views/.. but clearly, I am doing something very wrong as the error I'm getting is:
TypeError: Cannot call method 'getData' of undefined at c:\Users\Brian\documents\visualizer\app.js:21:24 at callbacks (c:\Users\Brian\documents\visualizer\node_modules\express\lib\router\index.js:164:37) at param (c:\Users\Brian\documents\visualizer\node_modules\express\lib\router\index.js:138:11) at pass (c:\Users\Brian\documents\visualizer\node_modules\express\lib\router\index.js:145:5) at Router._dispatch (c:\Users\Brian\documents\visualizer\node_modules\express\lib\router\index.js:173:5) at Object.router (c:\Users\Brian\documents\visualizer\node_modules\express\lib\router\index.js:33:10) at next (c:\Users\Brian\documents\visualizer\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.expressInit [as handle] (c:\Users\Brian\documents\visualizer\node_modules\express\lib\middleware.js:30:5) at next (c:\Users\Brian\documents\visualizer\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.query [as handle] (c:\Users\Brian\documents\visualizer\node_modules\express\node_modules\connect\lib\middleware\query.js:44:5)
If someone may point me to the right direction or explain to me what I am doing wrong, that would be appreciated
Thank you! (And sorry for the long read..)
Several different way to write it out:
// inputReader.js
module.exports.getData = function() {
return data();
}
// app.js
var inputReader = require('./inputReader'); // inputReader contains getData
inputReader.getData();
or
// inputReader.js
module.exports.getData = function() {
return data();
}
// app.js
var inputReader = require('./inputReader').getData; // inputReader is now getData
inputReader();
or
// inputReader.js
var theModule = {
getData : function() {
return data();
}
}
module.exports = theModule;
// app.js
var inputReader = require('./inputReader');
inputReader.getData();
or
// inputReader.js
var theModule = function() { /* constructor */ };
theModule.prototype.getData = function() {
return data();
};
module.exports = theModule;
// app.js
var inputReader = require('./inputReader');
new inputReader().getData();