Call function expression in external module - node.js

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(...);

Related

Check function name exists and call by String

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);
},
}

using a function which was imported from another module(node.js)

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.

Node.js module.exports parent/child variable reference

In node.js I have this scenario:
main.js
module.exports = {
dbHandler: {}
}
const DB_CONNECT = require('dbConnect.js');
const CHILD_MODULE = require('childModule.js');
module.exports.dbHandler = DB_CONNECT.connectDB(); // establishes the connection to the sqlite3 db
// ... give some time to module.exports.dbHandler to be loaded. (lab testing)
CHILD_MODULE.queryDB(); // <----- error occurs
childModule.js
var db = module.parent.exports.dbHandler;
//issue is here. Even after the parent have set dbHandler, this still empty {}.
module.exports.queryDB = function(){
db.all('SELECT * from mytable', (err, rows) => { // callback
console.log(rows);
}
Since DB_CONNECT.connectDB() is async, I give it a while (lab test) to load the database and updating module.exports.dbHandler before calling CHILD_MODULE.queryDB()
the error occurs when db.all is called.
TypeError: db.all is not a function
db still an empty object {}.
What is wrong in this code? How do I make the child's db to access the parent's module.exports.dbHandler ?
First of all, I will not fix your problem directly. I will try to explain my comment in above.
I have had a similar scenario in one of my projects. But I have used MongoDB. My db model looks like this:
var MongoClient = require('mongodb').MongoClient
var url = process.env.MONGO_URI
var collection = 'shortlinks'
var state = {
db: null
}
exports.connect = function (done) {
if (state.db) return done()
MongoClient.connect(url, function (err, db) {
if (err) return done(err)
state.db = db
done()
})
}
exports.get = function () {
return state.db
}
...
and some other methods
And I have accessed this module from different places for the same database connection with this line:
var db = require('../models/db')
I can access the same db instance with getter method and other methods as well.

Accessing module instance in express middleware

I'd like to have a node module, which exports a factory that returns instances of a class function.
//myModule.js
function MyClass(options) {
this.options = options || {};
}
MyClass.prototype.handle = function(req, res, next) {
//I want to access the instance here in the middleware function
console.log(this.options);
}
module.exports = function(options) {
return new MyClass(options);
}
Then, inside server.js, I'm attaching this middleware:
var myInstance = require("./myModule")({
foo: "bar"
});
app.use(myInstance.handle);
Inside the middleware function, this refers to something else (the global object maybe?), but I want to access the instance containing options. The only solution I could come up with was calling myInstance.handle.bind(myInstance), but that's not too friendly to the module's users. Is there another way to solve this problem, or is there a better way to do this kind of pattern entirely?
It's better to avoid using prototype whenever you can, and you can achieve what you're doing using something like this:
module.exports = function(opts) {
// private methods/vars
var options = opts || {};
return {
handle: function(req, res, next) {
console.log(opts);
}
}
}

How i can organize function in function in Nodejs?

As it is not possible in nodejs to use variables in required files directly i want to create one model object through which i would be able to reach all my models. For example i have something like this:
function User() {
this.get = function () {
console.log('getSomeUser');
}
}
function Post() {
this.send = function () {
console.log('sendSomePost');
}
}
module.exports = function Model () {
this.User = User();
this.Post = Post();
};
Then i require it like and should use like this:
var Model = require('model.js');
var model = new Model();
model.User.get();
model.Post.send();
Is it possible to do?
This works except your module.exports would have to look like:
module.exports = function Model () {
this.User = new User();
this.Post = new Post();
};
User and Post would need to be instantiated objects in order to use them they way that you are. You may also need to require model.js like so:
var Model = require('./model.js');
Personally I like this approach better:
module.exports = function(app){
var somelib = require('../path/somelib')(app),
//a 'private' method
function somethingPrivate(callback){
callback();
};
return {
User: function (req, res) {
somethingPrivate();
console.log('getSomeUser');
},
Post: function(req, res) {
console.log('sendSomePost');
}
}
}
now note that I am passing (app) into this function. this is so that if need be I can access app specific things that have already been loaded on init. It's not required though.
I then call this by doing this somewhere else, say in my controller:
module.exports = function(app){
var Model = require('../path/to/Model')(app);
app.get('/user', Model.User);
}
So lets look at this closer, if for example you don't want to pass app along the chain, then just do the following:
module.exports = function(){
//a 'private' method
function somethingPrivate(callback){
callback();
};
return {
User: function (req, res) {
somethingPrivate();
console.log('getSomeUser');
},
Post: function(req, res) {
console.log('sendSomePost');
}
}
}
then elsewhere you do:
var Model = require('../path/to/Model');

Resources