Serialization of a polymorphic array in node.js - node.js

I am looking for a method for serialization of a Javascript object, that contains several other objects of different classes, with function arguments.
Here is a simple test-case:
// Paper class:
function Paper(name) {
this.name = name;
}
Paper.prototype = {
string: function() { return "Paper:"+this.name; }
};
// Book class:
function Book(name) {
this.name = name;
}
Book.prototype = {
string: function() { return "Book:"+this.name; }
};
// Library class:
function Library(name) {
this.items = [];
}
Library.prototype = {
add: function(item) { this.items.push(item); },
string: function () {
var titles = this.items.map(function(item) { return item.string(); });
return titles.join(",");
},
};
///// Define a library:
var lib = new Library();
lib.add(new Paper("MyPaper"));
lib.add(new Book("MyBook"));
assert(lib.string() == "Paper:MyPaper,Book:MyBook");
///// Serialize, de-serialize and compare:
// var libString = serialize(lib);
// var newLib = deserialize(libString);
// assert(newLib.string() == "Paper:MyPaper,Book:MyBook");
NOTE: The main usage of de/serialization (at least in my case) is for moving complex objects to distant computers. For example, I want to build a big Library on my computer, then serialize it, put on a file, send the file to another computer, deserialize it there, and have the exact same Library.

You need to extend JSON semantics. If I were you, I would to something like this:
var protos = {}, //hash of prototypes
base = { //base prototype
toJSON: function () {
var props = {}; //properties to be serialized
for (var prop in this) { //this can be custimized, like taking `attrs` hash or something
if (this.hasOwnProperty(prop)) props[prop] = this[prop];
}
props.$proto = this.$proto; //need to copy this manually since it's not an `own propery`
return props;
}
};
function Paper(name) {
this.name = name;
}
protos.paper = Paper.prototype = Object.create(base);
Paper.prototype.$proto = 'paper';
Paper.prototype.toString = function() {
return 'Paper: ' + this.name;
}
function Book(name) {
this.name = name;
}
protos.book = Book.prototype = Object.create(base);
Book.prototype.$proto = 'book';
Book.prototype.toString = function() {
return 'Book: ' + this.name;
}
function Library(name) {
this.items = [];
}
Library.prototype = {
add: function(item) { this.items.push(item); },
toString: function () {
var titles = this.items.map(function(item) {
return item.toString();
});
return titles.join(',');
},
toJSON: function () {
return this.items.map(function(item) { return item.toJSON()});
}
};
Library.fromJSON = function (json) {
return json.map(function(item) {
var object = Object.create(protos[item.$proto]);
for (var prop in item) object[prop] = item[prop];
return object;
});
};
//test
var lib = new Library();
lib.add(new Paper('MyPaper'));
lib.add(new Book('MyBook'));
console.log(lib.toString());
var json = JSON.stringify(lib.toJSON());
console.log(Library.fromJSON(JSON.parse(json)).toString());
Here is a fiddle: http://jsfiddle.net/cSTT5/

I want to build a big Library on my computer, then serialize it, put on a file, send the file to another computer, deserialize it there, and have the exact same Library.
I've made an npm module named esserializer to solve this problem: save JavaScript class instance values recursively during serialization, in plain JSON format, together with its class name information. Then, during the deserialization stage, esserializer can recursively deserialize object instance, with all types/functions information retained, using the same class definition.
For your scenario, the code is pretty simple. It works if the serialized string is taken to another computer, as long as the same class definition exists on that machine:
const ESSerializer = require('esserializer');
// Paper class:
function Paper(name) {
this.name = name;
}
Paper.prototype = {
string: function() { return "Paper:"+this.name; }
};
Paper.prototype.constructor = Paper; // We need to redefine the constructor of Paper's prototype.
// Book class:
function Book(name) {
this.name = name;
}
Book.prototype = {
string: function() { return "Book:"+this.name; }
};
Book.prototype.constructor = Book;
// Library class:
function Library(name) {
this.items = [];
}
Library.prototype = {
add: function(item) { this.items.push(item); },
string: function () {
var titles = this.items.map(function(item) { return item.string(); });
return titles.join(",");
},
};
Library.prototype.constructor = Library;
///// Define a library:
var lib = new Library();
lib.add(new Paper("MyPaper"));
lib.add(new Book("MyBook"));
// assert(lib.string() == "Paper:MyPaper,Book:MyBook");
var serializedString = ESSerializer.serialize(lib);
// Later, on another machine, deserializedObj is a perfect copy of "lib":
var deserializedObj = ESSerializer.deserialize(serializedString, [Library, Book, Paper]);
console.log(deserializedObj.string()); // Paper:MyPaper,Book:MyBook

Related

How we call recursive function in node js

My code is below:
module.exports = {
cleanCode: function(){
return 'clean code helper'
},
nestedChildren: function(arr, parentId) {
var out = []
for (var i in arr) {
if (arr[i].parent_id == parentId) {
var children = nestedChildren(arr, arr[i].id)
if (children.length) {
arr[i].subCate = children
}
out.push(arr[i])
}
}
return out
}
}
Getting following error {"message":"nestedChildren is not defined"}
As #jonrsharpe suggested, move the function outside of the export:
let nestedChildren = function(arr, parentId) {
var out = [];
for (var i in arr) {
if (arr[i].parent_id == parentId) {
var children = nestedChildren(arr, arr[i].id);
if (children.length) {
arr[i].subCate = children;
}
out.push(arr[i]);
}
}
return out;
};
module.exports = {
nestedChildren,
cleanCode: function(){
return 'clean code helper';
}
};
Properties of an JavaScript Object cannot reference themselves or any other property of the same object. Thus, a recursive function within an object is not possible.
To work around this problem, you can move the function to the upper scope (outside of the object) where it's accessible from within the object.
So what I did was defining the function outside of the object as standalone function and then I referenced it in your export.
module.exports = {
nestedChildren,
...
};
is just a shorthand for
module.exports = {
nestedChildren: nestedChildren,
...
};

SyntaxError: Unexpected token

I searched for a similar question on google and the similar questions but to no help.
// file export_object.js
function Welcome(nameIn) {
this.name = nameIn;
}
Welcome.prototype = {
this.name = null,
showName: function () {
console.log("Hi exported object from contructor function " + name);
},
updateName: function(nameIn) {
this.name = nameIn;
}
};
module.exports = Welcome;
The problem is on the line
this.name = null,
// file server.js
var Welcome = require('export_object');
var w = new Welcome("Please update string");
w.updateName('Exported name:');
w.showName();
SyntaxError: Unexpected token .
The name is already assigned in the constructor, so explicitly defining an empty property in the prototype doesn't make sense. Just remove that line:
function Welcome(nameIn) {
this.name = nameIn;
}
Welcome.prototype = {
showName: function () {
console.log("Hi exported object from contructor function " + name);
},
updateName: function(nameIn) {
this.name = nameIn;
}
};
module.exports = Welcome;
If you had to put a name property on the prototype, the proper way to define a key-value pair is to separate them with a colon, eg
{
name: null,
Which would make the syntax proper, but would still be pretty odd to do in most situations.
Because here Welcome.prototype is an Object
so an object is always define as {"key":"value"}, so your syntax is wrong
function Welcome(nameIn) {
this.name = nameIn;
}
Welcome.prototype = {
resetName: function(){ this.name = null},
showName: function () {
console.log("Hi exported object from contructor function " + name);
},
updateName: function(nameIn) {
this.name = nameIn;
}
};
module.exports = Welcome;

Node.js: how to 'inherit' from abstract class?

I'm building a web app with node.js (+ angular, etc.).
The app will have to retrive some data (something like a catalog items list) from different providers, who expose their data in different ways.
In that module, I will have some function common to all providers, and some function unique to any of them.
My current (poor) implementation is something like this:
var providers = [
{ name: 'Apple', /* ... */ },
{ name: 'Samsung', /* ... */ },
{ name: 'Google', /* ... */ },
];
exports.syncCatalogues = function(search, callback) {
var allItems = [];
for (var p = 0; p < providers.length; p++) {
exports.getCatalog(providers[p], function(err, catalog) {
if (err) {
return callback(err);
}
exports.getItems(providers[p], catalog, function(err, items) {
if (err) {
return callback(err);
}
allItems = allItems.concat(items);
callback(null);
});
});
}
};
And my getCatalog() and getItems() implementation are as ugly as this:
exports.getCatalog(provider, callback) {
if (provider.name === 'Apple') {
// code for Apple provider ...
}
// and so on ...
};
exports.getItems(provider, callback) {
if (provider.name === 'Apple') {
// code for Apple catalog ...
}
// and so on ...
};
I know with ES5 (I'm stuck to it) abstract classes are not easy to implement, but I'm sure there is a better way (code more readable, maintainable, testable) than this... :-(
There are many ways to implement the inheritance in JavaScript.
Here is one, which I think the simplest, since you just operate with plain objects and use prototypal inheritance.
Instead of the base class you have a prototype object where you can place the common code.
Then you create an object based on the prototype and add specific code to it.
var providerPrototype = {
name: 'Prototype',
alertName: function() { // this is common function, all objects
alert(this.name); // will have it
}
};
var appleProvider = Object.create(providerPrototype);
appleProvider.name = 'Apple';
// this is a specific function for 'Apple'
appleProvider.getCatalog = function(callback) {
return callback(null, ['iPhone', 'Mac Mini']);
}
appleProvider.alertName = function() {
// call 'base' method
providerPrototype.alertName.call(this);
alert('All rights reserved.');
}
var samsungProvider = Object.create(providerPrototype);
samsungProvider.name = 'Samsung';
// this is a specific function for 'Samsung'
samsungProvider.getCatalog = function(callback) {
return callback(null, ['Galaxy S3', 'Galaxy S4']);
}
var providers = [
appleProvider, samsungProvider
];
var syncCatalogues = function(search, callback) {
var allItems = [];
for (var p = 0; p < providers.length; p++) {
var aProvider = providers[p];
aProvider.getCatalog(function(err, catalog) {
if (err) {
return callback(err);
}
aProvider.alertName(); // call the base method
alert(catalog);
});
}
};
syncCatalogues();
Check also Inheritance and the prototype chain in Mozilla javascript documentation.
And here is an example of splitting classes over node.js modules.
I'm new in nodeJS but I think my code below is possible only after ES6. I hope to help newbies like me. Follows:
class BaseClass {
constructor(){
console.log('Object created INHERITED');
}
toCallFromChild(){
console.log('Called by child');
this.toOverride();
}
toOverride(){} //to override
}
class childClass extends BaseClass{
toOverride(){
console.log ('Override by child');
}
}
var instance = new childClass();
instance.toCallFromChild();
My response is a possible alternative solution.
I personnally do not like the native javascript object mecanics. So i generaly use a library like Mootools for making clean objects.
Example from Mootools documentation :
var Animal = new Class({
initialize: function(age){
this.age = age;
}
});
var Cat = new Class({
Extends: Animal,
initialize: function(name, age){
this.parent(age); // calls initalize method of Animal class
this.name = name;
}
});
var myCat = new Cat('Micia', 20);
alert(myCat.name); // alerts 'Micia'.
alert(myCat.age); // alerts 20.
Se the online doc on : http://mootools.net/

Nodejs util.inherits produce unexpected results

Following code always prints 3 3 where as it should be printing 2 3 anything in any suggestions as to what I am doing wrong here ? or this is expected ?
var EventEmitter = require("events").EventEmitter,
util=require('util');
var Car=function(){
var self=this;
EventEmitter.call(this);
var make=1;
Car.prototype.getMake = function() {
return make;
};
Car.prototype.setMake = function(val) {
make=val;
return make;
};
}
util.inherits(Car, EventEmitter);
function Bmw(){
Car.call(this);
}
function Merc(){
Car.call(this);
}
util.inherits(Bmw, Car);
util.inherits(Merc, Car);
var car1=new Bmw();
car1.setMake(2);
var car2=new Merc();
car2.setMake(3);
console.log(car1.getMake(),car2.getMake());
var Car = function(){
var self=this;
EventEmitter.call(this);
var make=1;
Car.prototype.getMake = function() {
return make;
};
Car.prototype.setMake = function(val) {
make=val;
return make;
};
};
does not make sense. Car.prototype.getMake affects every single instance of Car, so what you are basically saying is, every time a new Car() instance is created, change the getMake and setMake function on ALL instances back to 1. Then when you call setMake it changes the make value for every instance
You either need to assign them explicitly to a single instance of Car. e.g.
var Car = function(){
EventEmitter.call(this);
var make=1;
this.getMake = function() {
return make;
};
this.setMake = function(val) {
make=val;
return make;
};
};
Or keep them on the prototype and use a different method for passing the value of make into the functions.
var Car = function(){
var self=this;
EventEmitter.call(this);
this.make_ = 1;
};
Car.prototype.getMake = function() {
return this.make_;
};
Car.prototype.setMake = function(val) {
this.make_ = val;
return this.make_;
};

Access private function in Node Module

I have a function exposed through export in a node module I'm building. I'd like to be able to have that function call an internal (private) function within the same module.
So far I have something like:
someModule.js
var publicFunc = function(a, b) {
var obj = {result: 'of some processing'};
return privateFunc(obj);
}
var privateFunc = function(obj) {
/* proccessing */
return result;
}
exports.publicFunc = publicFunc;
When publicFunc calls privateFunc I get:
Reference error: privateFunc is not defined;
Change your declarations to function name(... instead of var name = function(...
function publicFunc(a, b) {
var obj = {result: 'of some processing'};
return privateFunc(obj);
}
function privateFunc (obj) {
/* proccessing */
return result;
}
exports.publicFunc = publicFunc;

Resources