require appears to only work when placed inside exported object - require

Coming across something unexpected. I have the following code:
var actions = require("../actions.js"); // an object of objects
module.exports = {
rando_function: function(){
console.log(actions); // empty object
}
}
I expected to log an object of objects, but it's empty. Whereas, this works:
module.exports = {
rando_function: function(){
var actions = require("../actions.js"); // an object of objects
console.log(actions); // an object of objects
}
}
What am I doing wrong here?

Related

Error while using both module.exports and exports

I have read couple of posts on SO before posting this question. One thing that's not clear to me is why I'm not able to use multiply function when importing this as module. Isn't module.exports and exports refer to the same object?
Shouldn't multiply be added to the object that is referenced by module.exports. Since exports is an alias for module.exports, I was expecting I'm adding multiply to the same object as I'm not reassigning exports to refer to something else.
module.exports = {
sum : function(a,b){
return a+b;
}
};
exports.multiply = function(a,b){
return a*b;
};
Note that at the start of each nodejs module file, both exports and module.exports point at the same empty object. And you can assign properties to them like below:
exports.item1 = "hi1"
module.exports.item2 = "hi2"
Now both of the exports and module.exports have the same value:
{item1:"hi1", item2: "hi2"}
But when you assign objects to them, only the object that you have given to module.exports matters! In your case if you want to assign an object to module.exports and then add other functions to it, you should first assign the same object to both of them! Now they will point to the same object and if you assign another function to your exports object, it will be accessible via module.exports object, too.
Change the first line of your code and it will work fine!
exports = module.exports = {
sum : function(a,b){
return a+b;
}
};
exports.multiply = function(a,b){
return a*b;
};
You cannot access the multiply function because javascript objects are passed by reference. When you use the line module.exports = {blah}, you create a new object {blah} and set module.exports to point at it. However, exports still points to the old object.
Initially, module.exports and exports point to the same empty object.
So, exports = {} , module.exports = {}. But when you create a new object and have module.exports point at it, Eg:
module.exports = {
sum : function(a,b){
return a+b;
}
};
module.exports will point at the new object, but exports will still point at the old object:
// exports will still point to the old object
console.log(exports) // prints {}
console.log(module.exports) // prints { sum: function() }
Then:
console.log(exports) // prints {}
exports.multiply = function(a,b){
return a*b;
};
console.log(exports) // prints { multiply: function() }
When you import the module, you are returned the value in module.exports, so you won't have access to the multiply function, since that was defined in exports, which references a different object.
If you don't want to worry about this issue, you can just do:
exports = module.exports = {
sum : function(a,b){
return a+b;
}
};
This will make them reference the same object. Hence,
exports.multiply = function(a,b){
return a*b;
};
will work as normal.

i have already tried,but i don't no how to call the function in another file

sir/madam exlain the flow of node.js from client to server with the dynamic parameters passing from userinterface to api's based up on these parameters we will get the output from api.for example sabre api etc..
exports.flightDestinations = function(req, res) {
var callback = function(error, data) {
if (error) {
// Your error handling here
console.log(error);
} else {
// Your success handling here
// console.log(JSON.parse(data));
res.send(JSON.parse(data));
}
};
sabre_dev_studio_flight.airports_top_destinations_lookup({
topdestinations: '50'
}, callback);
};
we want this value 50 from user...and how to give this value?and how to call this function in node.js.
The exports variable is initially set to that same object (i.e. it's a shorthand "alias"), so in the module code you would usually write something like this:
var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;
to export (or "expose") the internally scoped functions myFunc1 and myFunc2.
And in the calling code you would use:
var m = require('mymodule');
m.myFunc1();
where the last line shows how the result of require is (usually) just a plain object whose properties may be accessed.
NB: if you overwrite exports then it will no longer refer to module.exports. So if you wish to assign a new object (or a function reference) to exports then you should also assign that new object to module.exports
It's worth noting that the name added to the exports object does not have to be the same as the module's internally scoped name for the value that you're adding, so you could have:
var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required
followed by:
var m = require('mymodule');
m.shortName(); // invokes module.myVeryLongInternalName

mongoose model inheritance within javascript prototypal object

Suppose you have a route initialization like this required in your main:
module.exports = function(app) {
for (var name in names) {
var schema = new Schema({}) // schema that accepts anything
, m = mongoose.model(name, schema)
, controller = new TextController(m)
app.get('/path', controller.create.bind(controller))
// etc, etc
And TextController is defined externally as:
var TextController = function(Model) {
this.Model = Model
}
TextController.prototype.create = function(req, res) {
var aDoc = this.Model({ // this is the problematic bit
title: req.body.title
, content: req.body.content})
aDoc.save(function(err) {...})
}
For some reason, mongo saves this as an empty document even though the title and content params are the expected strings. As expected, this.Model is some sort of mongoose object, but it seems to be rejecting the save or the instantiation. Any ideas or suggestions?
Note: I added the controller.method.bind(controller) because it was the only way (I knew of) to get access to this.Model.
Edit: I've also tried the following:
var TextController = function(myCollection) {
this.myCollection = myCollection
this.list = function(req, res) {
this.myCollection.find({}, function { ... })
}
}
And also tried passing in the name and initializing the model within the scope of the function function(name) { this.myCollection = mongoose.model(name) ... }
This turns out to be unrelated to javascript prototypes and completely due to how mongoose does Mixed Type Schemas:
In order to tell mongoose the document has changed you need to markModified(field)
example here: http://mongoosejs.com/docs/schematypes.html#mixed

How to access instance variables anywhere in the class for node.js

I am working on a node.js application with postgresql, using the express framework. I am trying to follow MVC as much as possible.
I want to generate query results in a model class and then pass them to a controller class. That controller class is actually defined in the routes, so that controller class can take the results and pass them as http response.
This is my database helper class, i.e. the model class. My problem is at the listener at the very end of the class.
exports.DatabaseHelper = function()
{
var allVenues;
var client;
var customEventEmitter;
this.init = function()
{
this.customEventEmitter = new events.EventEmitter();
client = new pg.Client(
{
host:'localhost',
port:5432,
database:'postgres',
user:'postgres',
password:'password'
});
}
this.getVenuesWithEvents = function(searchParams)
{
allVenues = new Array();
var query_for_venues;
this.init();
client.connect();
client.addListener("error",function()
{
sys.puts("postgresql interface error");
});
query_for_venues = client.query("select id, name, location, latitude, longitude, category_generalized from venues");
query_for_venues.addListener("row",function(row)
{
//some code
});
query_for_venues.addListener("end",function(result)
{
this.customEventEmitter.emit("data",allVenues);
//////////////////////////////////////////////////////////
//this line shows error....'this' refers to the query object so customEventEmitter is undefined
//customEventEmitter is my idea of sharing the query results to my controller class.
//but I cannot do this becasue of this error
console.log("after emission");
});
}
}
How can I access the customEventEmitter instance variable from within the listener?
Just remove this from your init function:
this.customEventEmitter = new events.EventEmitter();
So you'll have:
customEventEmitter = new events.EventEmitter();
And in your listener just emit the emitter without this as follows:
query_for_venues.addListener("end",function(result){
customEventEmitter.emit("data",allVenues);
console.log("after emission");
});
let me show you a nice trick.
you could change custom
var customEventEmitter;
to
this.customEventEmitter =null;
at the top of the function. then you can call
var self = this;
outside of the query function. then inside the query function you reference the outer "this" with self.
as in:
self.customEventEmitter.emit()
the methodology I just described is standard.

Instantiating objects with requireJS

I have a model object defined like this
blog.js
define({title: '', url: '', summary: ''});
I'm using the blog model to hold data from a service and I need to populate an array of blogs. How do I instantiate a new blog within a loop in another module?
I've tried passing in blog as a require object, but it maintains it's reference inside the loop leaving an array of the same object over and over again.
othermodule.js
define(['blog'], function(blog) {
//... more code
$.each(data, function(index, b) {
var tmpBlog = blog;
//...
list.push(tmpBlog);
});
});
I've also tried using var blog = require('blog'); yielding the same result.
So how do I instantiate the blog object using requirejs?
ok, I figured it out. I defined the blog model incorrectly. I needed to return a function blog(){...} instead like so:
define(function() {
return function blog() {
var self = this;
this.title = '';
//...
};
});
and the other module used it like this:
define(['models/blog'], function (model) {
var tmpBlog = new model();
tmpBlog.title = 'some title';
}

Resources