Currently I have a Node.js module with the following form :
var events = require('events');
var emitter = new events.EventEmitter();
function emitSomething() {
emitter.emit("event");
}
exports.emitSomething = emitSomething;
exports.on = emitter.on;
However any callback registered through on do not get called when I call emitSomething.
I can get around this by changing the last line to
exports.on = function(event, callback) { emitter.on(event, callback); };
Is there a reason I can't delegate the on function to a function defined in another module?
This is a common JS mistake. Note that the on method depends on this (which is emitter in your example). However, all you export is the function itself, so it's context (emitter) is lost when you call it later.
Here is a small example for this issue:
var someObj = {
doSth: function() { console.log(this) }
};
someObj.doSth(); // "Object { ..."
var doSth = someObj.doSth;
doSth(); // "Window { ..."
When I call doSth as method of someObj, this references someObj as expected. After I copied the function to doSth, this references it's new context, in the browser the global context Window. This is what happens in your case.
As you already mentioned, you have to bind the emitter context to the function. This can also be done like this:
exports.on = emitter.on.bind(emitter);
Related
In Meteor (a NodeJS Framework), there is a function called Meteor.userId() that always returns the userId that belongs to the current session as long as I am in a function that was original called from a Meteor Method.
The Meteor.userId() function utilizes meteors DDP?._CurrentInvocation?.get()?.connection. So somehow this "Magic line" gets my current DDP connection. This also works when burried deep inside of callbacks.
So somehow meteor sets a context that it refers to. I also want to do this kind of trick for another API that doesn't utilize meteors DDP but is a plain HTTP Api.
What I want to do:
doActualStuff = function(param1, param2, param3) {
// here, i am burried deep inside of calls to functions
// but the function at the top of the stack trace was
// `answerRequest`.
// I want to access its `context` here but without
// passing it through all the function calls.
// What I want is something like this:
context = Framework.getRequestContext()
}
answerRequest = function(context) {
//do some stuff
someFancyFunctionWithCallback(someArray, function(arrayPosition) {
aFuncCallingDoActualStuff(arrayPosition);
})
}
I can wrap the call to answerRequest if this is necessary.
I don't know how Meteor does it, but it doesn't look like magic. It looks like Meteor is a global object (window.Meteor in the browser or global.Meteor in Node.js) that has some functions that refer to some stateful object that exists in the context where they were defined.
Your example could be achieved by having answerRequest (or whatever function calls answerRequest, or whatever you want) call a setRequestContext function that sets the state that will be returned by getRequestContext. If you wanted, you could have an additional function, clearRequestContext, that cleans up after request is over. (Of course, if you have async code you'll need to take care that the latter isn't called until any code that needs that data has finished running.)
This is rudimentary, but it might look something like the below snippet. window.Framework does not need to be defined in the same file as the rest of the code; it just needs to be initialized before answerRequest is called.
let _requestContext = null;
window.Framework = {
setRequestContext(obj) {
_requestContext = obj;
},
getRequestContext() {
return _requestContext;
},
clearRequestContext() {
_requestContext = null;
},
};
const doActualStuff = function(param1, param2, param3) {
const context = Framework.getRequestContext()
console.log('Request context is', context);
}
const answerRequest = function(context) {
Framework.setRequestContext(context);
setTimeout(() => {
try {
doActualStuff();
} finally {
Framework.clearRequestContext();
}
}, 100);
}
answerRequest({ hello: 'context' });
.as-console-wrapper{min-height:100%}
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
I'm trying to add the event listener to my class, but it fails, telling me the object has no 'on' method.
Here's the class in its own file:
var events = require('events');
var util = require('util');
var Motion = function Motion (app) {
events.EventEmitter.call(this);
// Load models
app.loadModel('motion', 'motion');
this.on('testevent', function () {
console.log('an event has happened');
});
this.emit('testevent');
}
util.inherits(Motion, events.EventEmitter);
module.exports = Motion;
And here's how I instantiate it:
var Motion = require('./plugins/motion.js');
var motion = new Motion(app);
It looks like you may be asking for the constructor function itself to be an event emitter. Your code makes the objects produced by new with the constructor. i.e., the object motion produced at the end of your snippet should have an on method (as Vadim Baryshev notes, your code should work as you have it if this is the intent, and if that is the case you can ignore the rest of this answer).
If you really want the constructor to emit events, then take a look at this question and the answer I provided to it. However, it's not a great solution, and there appears to be no way of doing it without using the non-standard __proto__.
A better solution is to make a separate event emitter object for the constructor function to use for emissions. As much as I like the constructor-module pattern, it has to be discarded. Many node modules make the module itself the emitter, and have a function exposed by the module as a constructor. For example:
var events = require('events');
var util = require('util');
exports = module.exports = new events.EventEmitter();
exports.Motion = function (app) {
// Load models
app.loadModel('motion', 'motion');
// Emit event
exports.emit('testevent');
};
and to instantiate:
var motion = require('./plugins/motion');
motion.on('testevent', function () {
console.log('an object was constructed');
});
var motionObj = new motion.Motion(app);
Arrow_onmouseover is attached with the 'onmouseover' event of an object. I get a 'timeline is not defined' JS error when the onmouseover event occurs. I know this relates to the variable scope. How can I correct this.
function startloop()
{
var changer = setInterval("changecontents();", 2000);
var timeline = setInterval("change();", 2000);
}
window.onload = startloop();
function arrow_onmouseover()
{
window.clearInterval(timeline);
window.clearInterval(changer);
}
Also what is the difference between a function called as Function(); and Function; . I believe this may also be relevant here since it greatly affects the scope of a variable.
ie what is the difference between
onclick="js();" and onclick="js;" or onclick="js"
where JS is a defined Java Script function.
Change your code like this.
var timeline,changer;
function startloop()
{
changer = setInterval("changecontents();", 2000);
timeline = setInterval("change();", 2000);
}
window.onload = startloop();
function arrow_onmouseover()
{
window.clearInterval(timeline);
window.clearInterval(changer);
}
The difference between
onclick="js();" and onclick="js;" or onclick="js"
if your js function doesn't have any parameters to receive you can simple avoid () like if you want to get the date you can call new Date(); but instead you can simply call new Date;
I started using backbone.js recently for a game. I used model to create Timer as follows:
var Timer = Backbone.Model.extend({
defaults: {
'hh':00, 'mm':05, 'ss':00
},
initialize: function() {
},
countDownOnce: function() {
// Count down the time by 1 sec
},
run1: function() {
this.countDownOnce();
}
run2: function() {
setInterval(this.countDownOnce, 1000);
}
});
The countDownOnce function, if called directly as in run1, works fine.
But if the function is passed as an argument to some built-in function, say setInterval as in the run2 function, the value of this is lost.
How to propagate this pointer to the built-in functions?
The Backbone docs have a useful section on binding "this".
Basically, Underscore provides a couple of very useful functions, _.bind and _.bindAll, which help you more easily manage 'this's context.
...
initialize: function() {
_.bindAll(this, 'countDownOnce' //, and whatever other functions you want bound)
}),
...
This will make sure that no matter what context it's called from, the 'this' inside countDownOnce refers to your Timer instance.
One way to do this is using call and apply. For example:
run2: function() {
setInterval(this.countDownOnce.call, 1000, this);
}
Also note that passing a closure/function reference with arguments to setTimeout() and setInterval() requires some manual hacks to work correctly in IE.
this is how javascript was designed (pun intended :)
Basically 'this' binds to the current context so if in a function/method call like this:
var Data = function(name) {
this.name = name;
}
var myData = new Data("viky");
would refer to the name element "inside" Data (i.e., myData in this case)
Now if you had the following:
var Data = function(name) {
function morphName(anotherName) {
//and if you call this like this ;)
alert(this.name); //undefined
}
}
the inner function morphName is bound to the 'current' context i.e., the outer function. In javascript everything is an object, including functions. So the outer (anonymous) function doesn't have a member called name! (makes sense?)
In order to do that most people use the following (by convention):
var Data = function(name) {
var that = this; //capture current context. Some prefer self = this;
function morphName(anotherName) {
//then you access name like that ;)
alert(that.name);
}
}
I suggest you read about javascript closures and scopes to understand this and that :D