Calling a method from another method in Node.js - node.js

I am trying to make some modifications to a Node.js app that I forked, what I am trying to do is call a function within another one.
I have attempted a crack at this by simply calling the method as follows but I'm not really that familiar with Node.js so I'm not sure I'm doing it right.
'use strict';
/*
* initalize the class
*/
function MessageBot(bot, user, cache) {
this.bot = bot;
this.user = user;
this.cache = cache;
}
/*
* perform commands
*/
MessageBot.prototype.librarySearch = function(searchText) {
var self = this;
// call SOS function - this is the bit that doesn't work
MessageBot.prototype.callSos(somenumbervar);
}
MessageBot.prototype.callSos = function(number) {
// do something else here
var self = this;
var commandList = self.cache.get('commandList');
}

Remember that this ostensibly inherits the prototype (directly or indirectly). Therefore, you can just do this.callSos(somenumbervar).
If you want to reach the method through the prototype, you have to tell it what this is. With your current code, this in callSos() will be MessageBot.prototype -- certainly not what you want. So you can also do MessageBot.prototype.callSos.call(this, somenumbervar).
Which approach to take depends on how dynamic you want your objects to be. For example, if you want consumers of MessageBot to be able to "override" callSos() by installing their own method, then you should take the first approach (this.callSos()) as it will look up callSos in the object's inheritance chain. This process will only reach the method you've installed on the prototype if the method hasn't been overridden. IMO this is the approach you should take unless you have a very good reason not to.
See this example, which demonstrates how the two approaches differ regarding overriding, while also showing that both work with regards to passing the correct this value (since both methods can retrieve the expected value from this.data):
function ClassA(data) {
this.data = data;
}
ClassA.prototype.foo = function () {
console.log("this.bar() returned: " + this.bar());
console.log("ClassA.prototype.bar.call(this) returned: " + ClassA.prototype.bar.call(this));
};
ClassA.prototype.bar = function () {
return 'in the ClassA prototype, our data is ' + this.data;
};
console.log('--obj1-- (no override)');
var obj1 = new ClassA(3.14);
obj1.foo();
console.log('--obj2-- (override)');
var obj2 = new ClassA(42);
obj2.bar = function () {
return 'in an overriding method, our data is ' + this.data;
};
obj2.foo();

Related

nodejs referenceerror on nested function calls using async.series and async.until

I'm new to nodejs and trying to learn the basics by rebuilding an existing i2c sensor system.
Got it all running using a named functions and async.series inside a single file. To keep make reusable i now want to create a class which i then can import. unfortunatly i get some errors i don't understand.
class.js
const async = require('async');
const i2c = require('i2c-bus');
class Sensor {
constructor (channel) {
this.channel = channel;
var self = this;
}
openBus (callback) {
bus = i2c.open(self.channel, (err) => {callback()}); // shorted for stackoverflow
}
closeBus (callback) {
bus.close( (err) => {callback()}); //also shorted for better readability
}
connection (callback) {
/* first variation */
async.series([openBus, closeBus], callback);
connection2 (callback) {
/* second variation */
async.series([this.openBus, this.closeBus], callback);
}
}
module.exports = K30;
when i import the class, i can without any problem create a new sensor 'object' and call the functions directly using:
> var Sensor = require('./class.js');
> var mySensor = new Sensor(1);
> mySensor.openBus(foo);
> mySensor.closeBus(bar);
but if i go an try call the wrapper-functions, i get the following errors:
> mySensor.connection(foo);
ReferenceError: openBus is not defined (at 'connection')
> mySensor.connection2(foo);
ReferenceError: self is not defined (at 'openBus')
i believe those errors occure due to my lack of understanding the correct usage of this and self. sadly i can't find any good ead on that topic. any help is highly appreciated.
UPDATE
the solution provided in the first two anwsers was in fact my first approch before starting to use "self" (after some googling [this-that-trick]).
anyways, here is the output/error i get using "this.channel" instead:
> mySensor.connection2(foo);
TypeError: Cannot read property 'channel' of undefined (at openBus)
This is not saved anywhere var self = this; and therefore is lost when the function (constructor is function) ends.
Just remove the above line in constructor and use everywhere the this instead of self.
Its true that this keyword is little tricky in javascript, but if you follow reasonable approach, you should be fine.
You indeed have issue with this and self
Every member inside the class has to be referred by this. If you declare a variable named var EBZ-Krisemendt = "SO user";, to access it, you need to use it with this, eg: console.log(this.EBZ-Krisemendt);
What you need here is
openBus (callback) {
bus = i2c.open(this.channel, (err) => {callback()});
}
and then mysensor.connection2(foo) will work fine.
while i still don't fully understand the reason behind this i fixed my code by getting rid of that "ES6" class definition.
class.js
const i2c = require('i2c-bus');
const async = require('async');
function Sensor(channel) {
let that = this; // make 'this' available in sub-function scope
this.channel = channel;
function openBus(cb) {
// open the bus-connection
bus = i2c.open(that.channel);
}
function closeBus(cb) {
// close the bus-connection
}
function connection(cb) {
async.series([openBus, closeBus], cb);
}
function getReading(cb) {
async.until(
function() {
// loop condition e.g. max tries to get reading
},
function(cb) {
connection(cb); // calling nested synchronous connection-routine
},
function (err) {
// result handling
}
); // end async.until
} // end getReading
return {
getReading: getReading
} // make only 'getReading' available
}
module.exports = {
Sensor: Sensor
} // make 'Sensor' available
in the 'member'-functions i can now use the 'class'-variables of 'Sensor' by accessing them with 'that' (e.g.: 'that.channel')
Detail:
function openBus(cb){
bus = i2c.open(that.channel);
}
if i'd use this instead of that it would only work while calling openBus directly. in my example it's neccessary to call openBus and closeBus in a synchronous manner (for obvious reasons). since async.series is additionally nested inside async.until (sensor might need several tries to response) the scope of this changes. by using that instead i'm able to ignore the scope.
Comment:
since the solution is kinda generally pointing to using nested async-calls inside custom modules i'll slightly alter the titel of the initial question. i'm still hoping for better solutions and/or explanations, so i won't mark my own anwser as accepted yet.

How to create some kind of context in a NodeJS application, I can access in all functions I call from there?

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%}

Subclassing, extending or wrapping Node.js 'request' module to enhance response

I'm trying to extend request in order to hijack and enhance its response and other 'body' params. In the end, I want to add some convenience methods for my API:
var myRequest = require('./myRequest');
myRequest.get(function(err, hijackedResponse, rows) {
console.log(hijackedResponse.metadata)
console.log(rows)
console.log(rows.first)
});
According to the Node docs on inherits, I thought I could make it work (and using the EventEmitter example in the docs works OK). I tried getting it to work using #Trott's suggestion but realized that for my use case it's probably not going to work:
// myRequest.js
var inherits = require('util').inherits;
var Request = require("request").Request;
function MyRequest(options) {
Request.call(this, options);
}
inherits(MyRequest, Request);
MyRequest.prototype.pet = function() {
console.log('purr')
}
module.exports = MyRequest;
I've been toying with extend as well, hoping that I could find a way to intercept request's onRequestResponse prototype method, but I'm drawing blanks:
var extend = require('extend'),
request = require("request")
function myResponse() {}
extend(myResponse, request)
// maybe some magic happens here?
module.exports = myResponse
Ended up with:
var extend = require('extend'),
Ok = require('objectkit').Ok
function MyResponse(response) {
var rows = Ok(response.body).getIfExists('rows');
extend(response, {
metadata: extend({}, response.body),
rows: rows
});
response.first = (function() {
return rows[0]
})();
response.last = (function() {
return rows[rows.length - 1] || rows[0]
})();
delete response.metadata.rows
return response;
}
module.exports = MyResponse
Keep in mind in this example, I cheated and wrote it all inside the .get() method. In my final wrapper module, I'm actually taking method as a parameter.
UPDATED to answer the edited question:
Here's a rough template for the contents of your myResponse.js. It only implements get(). But as a bare bones, this-is-how-this-sort-of-thing-can-be-done demo, I hope it gets you going.
var request = require('request');
var myRequest = {};
myRequest.get = function (callback) {
// hardcoding url for demo purposes only
// could easily get it as a function argument, config option, whatever...
request.get('http://www.google.com/', function (error, response, body) {
var rows = [];
// only checking error here but you might want to check the response code as well
if (!error) {
// mess with response here to add metadata. For example...
response.metadata = 'I am awesome';
// convert body to rows however you process that. I'm just hardcoding.
// maybe you'll use JSON.parse() or something.
rows = ['a', 'b', 'c'];
// You can add properties to the array if you want.
rows.first = 'I am first! a a a a';
}
// now fire the callback that the user sent you...
callback(error, response, rows);
});
};
module.exports = myRequest;
ORIGINAL answer:
Looking at the source code for the Request constructor, it requires an options object that in turn requires a uri property.
So you need to specify such an object as the second parameter in your call():
Request.call(this, {uri: 'http://localhost/'});
You likely don't want to hard code uri like that inside the constructor. You probably want the code to look something more like this:
function MyRequest(options) {
Request.call(this, options);
}
...
var myRequest = new MyRequest({uri: 'http://localhost/'});
For your code to work, you will also need to move util.inherits() above the declaration for MyRequest.prototype.pat(). It appears that util.inherits() clobbers any existing prototype methods of the first argument.

Propogation of *this* in nested function calls in Backbone.js

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

Namespacing a javascript library, as optional

I'm about to start building a JS library that will have multiple modules. Let's suppose the library is called Library, and two modules will be called One and Two. I'd like for end users to be able to call the library in two different ways:
Library.One.somefunction(params)
or
somefunction(params)
Basically, I want to give the end users the option of including a namespace or not. Is there a good way to do this? Also, is there a good way to do this if I also want to provide a minified version of the library? This library is something that I could end up in Node.js; for now, I'm going to use it myself, but I want to design it in such a way that it's not too hard to turn in to a sharable project in the future.
Any references you can point me to would be great, thanks!
If you're using Node.js you could leverage the CommonJS module system.
math.js (your library)
exports.add = function() {
for (var i = arguments.length; i--;) {
sum += arguments[i];
}
return sum;
};
program.js (someone using it...)
var MyMath = require('math');
console.log(MyMath.add(1, 2)); // 3
// ... in different ways
var add = require('math').add;
console.log(add(1, 2)); // 3
The basic idea behind making a "namespace" optional is to assign the functions to the global scope, which is the window object:
window.somefunction = Library.One.somefunction;
You can write an include function that works similar to other languages:
var include = function (library, p) {
if (!p) {
for (var prop in library) {
if (library.hasOwnProperty(prop)) {
window[prop] = library[prop];
}
}
} else {
window[p] = library[p];
}
};
Then just do, as required:
include(Library.One);
Or use particular functions only:
include(Library.One, 'somefunction');
Warnings:
Executing the functions without the dot notation (One.somefunction) will cause the this keyword to refer to window rather than Library.One. This isn't a problem if you don't use this at all. If you have data to share to between functions then you can do so using closure scope instead of this:
var Library = {};
(function () {
// I'm a closure, I have local scope
var sharedData = "I'm shared but private to this scope";
Library.One = {};
Library.One.funcOne = function () {
alert(sharedData);
};
Library.One.funcTwo = function () {
sharedData += "!";
};
}) ();
Others have well-advised not to make your methods global. This is because once it is global, it is global for all files, and therefore likely to conflict with other code. What you can do is modify the import function above to create a new object, and assign everything to that object before returning it. Then files that need shortcuts to particular libraries can do:
(function () {
var _ = include(Library.One); // This stays within this scope
_.somefunction();
})();
well, i don't know what you mean by "good way".
First of all, the whole purpose of a namespace is to collect variables that are related and not scatter them all around your public namespace.
Personally I wouldn't use such a thing, but you could loop through your namespace's objects and attach them to the window :
for(var i in Namespace)
if(Namespace.hasOwnProperty(i))
window[i] = Namespace[i];
You could do this pretty easily, but are you certain you want to make all the methods global properties?
You could implement it like this (very simplified):
(function( window, undefined ) {
// Your code setting up namespaces
var Library = {One:{},Two:{}};
// function for adding library code to both namespaces.
// Could be modified to accept an Array of functions/names
function addToLibraryOne( id, fn ) {
window[id] = Library.One[id] = fn;
}
// add a function
addToLibraryOne( "somefunction", function( params ) {
// function code
});
window.Library = Library;
})( window );
I'd wonder if you really want to pollute the global namespace like this.
At the very least, I'd make the global properties an option, then only have the function add those if that option is selected.
Well, the second one means that you also want the functions and object and whatever in your modules to be in the global scope. Entirely possible of course, but so against best practices as to be somewhat abhorrent.
For the first part, just declare your Library namespace globally:
var Library = {};
and then start populating it with your modules:
Library.One = {};
Library.Two = {};
and then start adding the functionality to those modules.
(function($) {
var $.froobString = function(s) { .... };
...etc...
})(Library.One);
(Here I've done it as a self-executing anonymous function that passes in Library.One as $.)
To convert all that to globals, have a routine like this:
var convertToGlobals = function(module) {
for (name in module) {
window[name] = module[name];
}
};
convertToGlobals(Library.One)
But then again I'd advise against it.
I might be wrong about this (so this might get downvoted, but I want this evaluated), but I think you are setting up a contradiction with the requirements
1) I want to use namespaces
2) I want to be able to access namespace functionality without the namespace.
basically 2 is "I dont want namespaces".
For implementation, you could just define a bunch of functions globally that route into the namespace, but then why have the namespace to begin with?

Resources