How we call recursive function in node js - 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,
...
};

Related

Variable precedence (global in node js?)

"use strict";
var Tabletop = require("tabletop");
var base64 = require('base-64');
Tabletop.init( { key: 'xxxxxg46hgfjd',
callback: showInfo,
simpleSheet: true } )
function showInfo(data, tabletop) {
console.log(data);
console.log(base64.encode(data));
}
var vGlobals = {
dataString: base64.encode(data)
};
module.exports = vGlobals;
How can I access the data variable from showInfo, to use in vGlobals? It says that it hasn't been defined.
Your approach is wrong, you can't do it this way because TableTop call your callback asynchronously.
My suggestion (a quick one) :
var dataString = null;
module.exports = function(cb) {
if (dataString == null)
Tabletop.init({
key: 'xxxxxg46hgfjd',
callback: function(data, tabletop) {
dataString = base64.encode(data);
cb(dataString);
},
simpleSheet: true
});
else cb(dataString);
};
And to get the data :
var dataManager = require('./myfile');
dataManager(function(dataString) {
//here is your data do what you want with it
})
You should look/learn more about node/javascript and asynchronous/event-driven programing.

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;

Serialization of a polymorphic array in 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

Knockout-2.2.0, subscribe get value before change AND new value

jsfiddle link: http://jsfiddle.net/T8ee7/
When I call Knockout's subscribe method is there a way I can get both the previous and new value? Right now, I can only call get these values separately.
I want to trigger some code if the old and new value are different.
I suppose I could do the following, but it can get messy...
(http://jsfiddle.net/MV3fN/)
var sv = sv || {};
sv.PagedRequest = function (pageNumber, pageSize) {
this.pageNumber = ko.observable(pageNumber || 1);
this.numberOfPages = ko.observable(1);
this.pageSize = ko.observable(pageSize || sv.DefaultPageSize);
};
var _pagedRequest = new sv.PagedRequest();
var oldValue;
_pagedRequest.pageNumber.subscribe(function (previousValue) {
console.log("old: " + previousValue);
oldValue = previousValue;
}, _pagedRequest, "beforeChange");
_pagedRequest.pageNumber.subscribe(function (newValue) {
console.log("new: " + newValue);
if (oldValue != newValue) {
console.log("value changed!");
}
});
_pagedRequest.pageNumber(10);
_pagedRequest.pageNumber(20);
​
I prefer using an observable extender.
http://jsfiddle.net/neonms92/xybGG/
Extender:
ko.extenders.withPrevious = function (target) {
// Define new properties for previous value and whether it's changed
target.previous = ko.observable();
target.changed = ko.computed(function () { return target() !== target.previous(); });
// Subscribe to observable to update previous, before change.
target.subscribe(function (v) {
target.previous(v);
}, null, 'beforeChange');
// Return modified observable
return target;
}
Example Usage:
// Define observable using 'withPrevious' extension
self.hours = ko.observable().extend({ withPrevious: 1 });
// Subscribe to observable like normal
self.hours.subscribe(function () {
if (!self.hours.changed()) return; // Cancel if value hasn't changed
print('Hours changed from ' + self.hours.previous() + ' to ' + self.hours());
});
This seems to work for me
ko.observable.fn.beforeAndAfterSubscribe = function (callback, target) {
var _oldValue;
this.subscribe(function (oldValue) {
_oldValue = oldValue;
}, null, 'beforeChange');
this.subscribe(function (newValue) {
callback.call(target, _oldValue, newValue);
});
};
See more at: http://ideone.com/NPpNcB#sthash.wJn57567.dpuf
http://jsfiddle.net/MV3fN/3/
var sv = sv || {};
sv.PagedRequest = function (pageNumber, pageSize) {
var self = this;
self.pageNumber = ko.observable(pageNumber || 1);
self.numberOfPages = ko.observable(1);
self.pageSize = ko.observable(pageSize || sv.DefaultPageSize);
self.pageNumber.subscribe(function (previousValue) {
console.log(previousValue);
console.log(self.pageNumber.arguments[0]);
if (previousValue != _pagedRequest.pageNumber.arguments[0]) {
console.log('value changed');
}
else {
//This won't get executed because KO doesn't
//call the function if the value doesn't change
console.log('not changed');
}
}, _pagedRequest, "beforeChange");
};
var _pagedRequest = new sv.PagedRequest();
_pagedRequest.pageNumber(10);
_pagedRequest.pageNumber(20);
_pagedRequest.pageNumber(20);
_pagedRequest.pageNumber(5);
I don't know if you're really supposed to use arguments[0], but it seems to work.
You could also set up your own method to accomplish this in a much cleaner way:
http://jsfiddle.net/PXKgr/2/
...
self.setPageNumber = function(page) {
console.log(self.pageNumber());
console.log(page);
if (self.pageNumber() != page) {
console.log('value changed');
}
else {
console.log('not changed');
}
self.pageNumber(page);
};
...
_pagedRequest.setPageNumber(10);
_pagedRequest.setPageNumber(20);
_pagedRequest.setPageNumber(20);
_pagedRequest.setPageNumber(5);

mongodb data async in a for-loop with callbacks?

Here is a sample of the working async code without mongodb. The problem is, if i replace the vars (data1_nodb,...) with the db.collection.find(); function, all needed db vars received at the end and the for()-loop ends not correct. Hope someone can help. OA
var calc = new Array();
function mach1(callback){
error_buy = 0;
// some vars
for(var x_c99 = 0; x_c99 < array_temp_check0.length;x_c99++){
// some vars
calc[x_c99] = new Array();
calc[x_c99][0]= new Array();
calc[x_c99][0][0] = "dummy1";
calc[x_c99][0][1] = "dummy2";
calc[x_c99][0][2] = "dummy3";
calc[x_c99][0][3] = "dummy4";
calc[x_c99][0][4] = "dummy5";
function start_query(callback) {
data1_nodb = "data1";
data2_nodb = "data2";
data3_nodb = "data3";
data4_nodb = "data4";
calc[x_c99][0][0] = data1_nodb;
calc[x_c99][0][1] = data2_nodb;
calc[x_c99][0][2] = data3_nodb;
callback(data1_nodb,data2_nodb,etc..);
}
start_query(function() {
console.log("start_query OK!");
function start_query2(callback) {
data4_nodb = "data5";
data5_nodb = "data6";
data6_nodb = "data7";
calc[x_c99][0][3] = data4_nodb;
calc[x_c99][0][4] = data5_nodb;
callback(data5_nodb,data6_nodb,etc..);
}
start_query2(function() {
console.log("start_query2 OK!");
function start_query3(callback) {
for(...){
// do something
}
callback(vars...);
}
start_query3(function() {
console.log("start_query3 OK!");
});
});
});
}
callback(calc);
};
function mach2(callback){
mach1(function() {
console.log("mach1 OK!");
for(...){
// do something
}
});
callback(calc,error_buy);
};
mach2(function() {
console.log("mach2 OK 2!");
});
You need to work with the async nature of the collection.find() method and wait for all of them to be done. A very popular approach is to use the async module. This module allows you run several parallel tasks and wait for them to finish with its async.parallel() method:
async.parallel([
function (callback) {
db.foo.find({}, callback);
},
function (callback) {
db.bar.find({}, callback);
},
function (callback) {
db.baz.find({}, callback);
}
], function (err, results) {
// results[0] is the result of the first query, etc
});

Resources