How to "subclass" a node.js module - node.js

I've been primarily a Perl coder for years, but also have a background in C++, so I'm coming from a "classical" OO background, and now learning node.js. I just read through The Principles of Object-Oriented JavaScript, which did a good job of explaining the JS concept of OO to classically-minded people like me. But I'm left with a question, specifically related to node.js and inheritance. Pardon me if I'm still using "classical" vocabulary to explain my problem.
Lets suppose I have a module lib/foo.js:
function foo() {
console.log('Foo was called');
}
module.exports.foo = foo;
And I want to "subclass" this in another module lib/bar.js:
var foo = require('foo.js');
// Do some magic here with *.prototype, maybe?
function bar() {
console.log('Bar was called');
}
module.exports.bar = bar;
Such that my main script can do this:
var bar = require('lib/bar.js');
bar.foo(); // Output "Foo was called"
bar.bar(); // Output "Bar was called"
Is this even possible? If so, what am I missing?
Or is this an anti-pattern? Or plain impossible? What should I do instead?

Here's how I did it, to override one method in the request module. Warning: many node modules are poorly designed for extension, including request, as they do way too much stuff in the constructor. Not just a gazillion argument options, but starting up IO, connections, etc. For example, request does the http connection (eventually) as part of the constructor. There is no explicit .call() or .goDoIt() method.
In my example, I wanted to use querystring instead of qs to format forms. My module is cleverly named "MyRequest". In a separate file named myrequest.js you have:
var Request = require('request/request.js');
var querystring = require('querystring');
MyRequest.prototype = Object.create(Request.prototype);
MyRequest.prototype.constructor = MyRequest;
// jury rig the constructor to do "just enough". Don't parse all the gazillion options
// In my case, all I wanted to patch was for a POST request
function MyRequest(options, callbackfn) {
"use strict";
if (callbackfn)
options.callback = callbackfn;
options.method = options.method || 'POST'; // used currently only for posts
Request.prototype.constructor.call(this, options);
// ^^^ this will trigger everything, including the actual http request (icky)
// so at this point you can't change anything more
}
// override form method to use querystring to do the stringify
MyRequest.prototype.form = function (form) {
"use strict";
if (form) {
this.setHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8');
this.body = querystring.stringify(form).toString('utf8');
// note that this.body and this.setHeader are fields/methods inherited from Request, not added in MyRequest.
return this;
}
else
return Request.prototype.form.apply(this, arguments);
};
Then, in your application, instead of
var Request = require("request");
Request(url, function(err, resp, body)
{
// do something here
});
you go
var MyRequest = require("lib/myrequest");
MyRequest(url, function(err, resp, body)
{
// do that same something here
});
I'm not a JavaScript guru so there may be better ways...

For reference, the specific solution I came up with to my sample code problem follows:
In lib/foo.js:
var Foo = function() {}
Foo.prototype.foo = function() {
console.log('Foo was called!');
};
module.exports = new Foo;
In lib/bar.js:
var foo = require('./foo.js');
var Bar = function() {}
Bar.prototype = Object.create(foo.__proto__);
Bar.prototype.constructor = Foo;
Bar.prototype.bar = function() {
console.log('Bar was called!');
};
module.exports = new Bar;
Then in my test script:
var bar = require('lib/bar.js');
bar.foo(); // Output "Foo was called"
bar.bar(); // Output "Bar was called"

Related

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.

Node.js EventEmitter - bad things are happening

I've been trying to resolve a bug in a nodejs application, and have narrowed it down to the way I've implemented event emitters. The application is an express.js app, has uses classes. There's some critical aspect of NodeJS that I must be missing, around memory usage and class / object lifecycles. I was hoping someone could point out why what I'm doing is not working as expected.
Here's the code:
// ServiceWrapper.js:
var events = require('events');
var ServiceClient = function(opts) {
this.foobar = "";
this.opts = opts;
this.hasFoo = false, this.hasBar = false;
}
ServiceClient.prototype = new events.EventEmitter();
ServiceClient.prototype.getFoo = function() {
var self = this;
self.hasFoo = true;
self.foobar += "foo";
self.emit('done','foo');
}
ServiceClient.prototype.getBar = function() {
var self = this;
self.hasBar = true;
self.foobar += "bar";
self.emit('done','bar');
}
var ServiceWrapper = function(){}
ServiceWrapper.prototype.getResponse = function(options, callback) {
var servClient = new ServiceClient({});
servClient.on('done', function(what) {
if (servClient.hasFoo && servClient.hasBar) {
console.log("foo && bar")
callback(servClient.foobar);
}
else {
console.log("Don't have everything: " + servClient.foobar);
}
});
servClient.getFoo();
servClient.getBar();
}
module.exports = ServiceWrapper
And then in my express app:
var ServiceWrapper = require('ServiceWrapper');
app.get('/serviceReponse', function(req,res) {
var servWrapper = new ServiceWrapper();
servWrapper.getResponse(function(ret) {
res.end(ret);
});
});
The behaviour on the web app works as expected: response is set to "foobar". However, looking at the logs, it looks like there's a memory leak - multiple instances of servWrapper. After starting the application, the first request generates:
Don't have everything: foo
foo && bar
However, if I refresh the page, I see this:
foo && bar
Don't have everything: foo
foo && bar
foo && bar
And with every refresh, the listener detects multiple 'done' events - foo && bar outputs keeps growing (assuming there's more and more instances of ServiceWrapper that persist in memory).
Why does this happen? (I expect to see the output that I get on the first request from every request).
Thanks to the guys on #node.js on freenode for assisting with this:
sure, but every time you attach listeners, you're attaching them to the same emitter
since you didn't localize the prototype's state to your instance, the prototype methods act upon the state of the prototype object.
I believe you can fix it by simply doing EventEmitter.call(this) in the constructor
See the following link for more info:
http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor

Knockout Declarations

I am new for knockout. I would like to know the differences between these three and which one is best as per latest framework.
Approach 1 (InvoiceTypes): Declaring all variables and methods using comma and finally using return statement to expose public interface methods.
Approach 2 (OrderTypes): It is similar to Approach 1 but used semicolon to differentiate each variable or method.
Apprach 3 (ModelTypes): It is similar to Approach 2 but with out return statement.
Finally specified calling way of start method in each approach in jquery read.
Approach 1
window.Domain = window.Domain || {}
window.Domain.InvoiceTypes = function () {
var types = ko.observableArray(),
getTypes = function() { return types; },
start = function() {
types.push({name:"knockout"});
},
submit = function() {
alert("submit");
};
return {
getTypes: getTypes,
start: start,
submit: submit
};
}();
Approach 2
window.Domain.OrderTypes = function () {
var types = ko.observableArray();
var getTypes = function() { return types; };
var start = function() {
types.push({name:"knockout"});
};
var submit = function() {
alert("submit");
};
return {
getTypes: getTypes,
start: start,
submit: submit
};
}();
Approach 3
window.Domain.ModelTypes = function () {
var self = this;
self.types = ko.observableArray();
self.getTypes = function() { return types; };
self.start = function() {
types.push({name:"knockout"});
};
self.submit = function() {
alert("submit");
};
};
<script type="text/javascript">
$(document).ready(function() {
window.Domain.InvoiceTypes.start();
window.Domain.OrderTypes.start();
var obj = new window.Domain.ModelTypes();
obj.start();
});
</script>
The difference I can see clearly is, single var declaration & return statement and using of self by this keyword.
Please provides your inputs.
Approaches #1 and #2 are akin to static factory methods. Rather than creating an object with the new keyword, you are calling a static "factory" function that creates and returns a new type for you. As for the comma versus semicolon approach, both are valid, but I prefer semicolons over commas. Why? Because javascript is more forgiving with semicolons than with commas. You can omit a semicolon here and there and the script will still run, whereas commas must always be present for the javascript to be correctly parsed. It is also easier to read with semicolons when your script gets larger.
Approach #3 is what most knockout developers do, or should to. Firstly, because you don't need the little () at the end of your function declaration, so it looks more like a class. However, it looks like you have an error in there:
self.start = function() {
//types.push({name:"knockout"}); // types was not declared,
self.types.push({name:"knockout"}); // only self.types was declared
};
... same error here
self.getTypes = function() {
//return types; types was never declared
return self.types;
};

hogan.js how to debug a variable

i'm very familiar with the javascript console.log(), and the php_dump() functions that allows us to see what's in a variable, i want to know if there is some function like this in hogan.js that let us inspect the content of a variable.
add some method to your data and include it at the loctation you need to inspect the scope
var data = {
...
// your vars,
...
inspect: function () {
return function () {
console.log(this);
}
}
};
template.render(data);
anywhere you use {{inspect}} it will log the current render context in the console
I slightly modified it to add the function to the data packet that is passed to Hogan in a centralized position, which, in my code, is a function called render().
Thank you for this clever trick.
function render(template, data, destination) {
data.inspect = function() {
return function() {
console.log("inspect:")
console.log(this);
};
};
// localized strings
data.strings = app.strings;
var tmpl = Hogan.compile(template);
var content = tmpl.render(data);
document.querySelector(destination).innerHTML = content;
}

Node JS : Requesting for code snippet explanation

I am just curious to know what is the purpose of,
function MyStream() {
events.EventEmitter.call(this);
}
in the following block of code taken from Nodejs.org Docs section,
var util = require("util");
var events = require("events");
function MyStream() {
events.EventEmitter.call(this);
}
util.inherits(MyStream, events.EventEmitter);
MyStream.prototype.write = function(data) {
this.emit("data", data);
}
var stream = new MyStream();
console.log(stream instanceof events.EventEmitter); // true
console.log(MyStream.super_ === events.EventEmitter); // true
stream.on("data", function(data) {
console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"
Please explain.
This isn't the first time this question has been asked: https://groups.google.com/forum/#!topic/nodejs/ab_Xih1L5R8/discussion
Quote from Bradley Meck:
Using EventEmitter.call on an object will do the setup of instance methods / properties (not inherited) of an EventEmitter. It is similar in purpose to super(...) in Java or base(...) in C#, but it is not implicit in Javascript. Because of this, we must manually call it ourselves. As for the talk about util.inherits, this will make the MyStream function inherit from another prototyped function so that instanceof works (side note: javascript only allows single inheritance). Due to how the new operator works, if we have the this variable in a function set to an instanceof EventEmitter, and call EventEmitter.call it look for all intents and purposes as if EventEmitter's constructor is being called on our MyStream object.

Resources